將層數很深的 object 加以解構

若 function 的參數是很深層的 object,可以使用 ES2015 的 Object Destructuring 加以解構,除此之外,也可以使用 Ramda 的 path()

Version


WebStorm 2018.3.3
Quokka 1.0.136
Ramda 0.26.1

Non Proint-free


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { assoc, map } from 'ramda';

const obj = {
data: {
books: [
{ id: 1, title: 'Functional Programming in JavaScript' },
{ id: 2, title: 'RxJS in Action' },
{ id: 3, title: 'Speaking JavaScript' },
],
},
};

const addProp = (k, v) => ({ data: { books } }) => map(assoc(k, v), books);

const result = addProp('desc', 'Not selected')(obj);
console.dir(result);

由於 ECMAScript 的 object 特性,實務上常常會遇到層數很深的 object,ES2015 提供了 Object Destructuring,讓我們可以在 parameter list 就加以解構,非常方便。

path000

Point-free


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { map, assoc, pipe, path } from 'ramda';

const obj = {
data: {
books: [
{ id: 1, title: 'Functional Programming in JavaScript' },
{ id: 2, title: 'RxJS in Action' },
{ id: 3, title: 'Speaking JavaScript' },
],
},
};

const addProp = (k, v) => pipe(
path(['data', 'books']),
map(assoc(k, v)),
);

const result = addProp('desc', 'not selected')(obj);
console.dir(result);

(k, v) 由於是條件部分,無法省略,但 ({ data: { books } }) 屬 data 部分,是否有機會 Point-free 呢 ?

path()
[Idx] → {a} → a | Undefined
將層數很深的 object 加以解構

[Idx]:array,描述要解構的 property

{a}:要解構的 object

a | Undefined:若能解構則回傳 a,若無法解構成回傳 undefined

13 行

1
2
3
4
const addProp = (k, v) => pipe(
path(['data', 'books']),
map(assoc(k, v)),
);

({ data: { books } }) 省略,直接由 pipe() 傳給 path() 第二個參數,而 path() 第一個參數則以 array 形式描述要解構的 property,如同 Object Destructuring 一樣。

path() 解構之後,再將 array 傳給 map() 的第二個參數。

如此 addProp() 就 Point-free 了。

path001

Conclusion


  • 參數為 object 時,固然可以使用 Object Destructuring 加以解構,但也可使用 Ramda 的 path(),可讀性更好,還可以 Point-free

Reference

Ramda, map()
Ramda, assoc()
Ramda, pipe()
Ramda, path()