若想一次寫入多個 Property 且 Immutable,ECMAScript 的 Property Shorthand 與 Ramda 的 assoc()
與 set()
都有其極限,Wink-fp 的 mix()
可讓我們一次滿足兩個願望。
Version
macOS Catalina 10.15.4
VS Code 1.43.2
Quokka 1.0.284
ECMAScript 2015
Ramda 0.27.0
Wink-fp 1.20.60
ECMAScript
let obj = {
price: 100
}
let title = 'Speaking JavaScript'
let price = 200
let result = { ...obj, title, price } // ?
若 obj
原有 price
property,我們希望以原來 object 為基礎修改 price
property 並新增 title
property,並且原來 object 維持 immutable。
ES6 可使用 object spread 展開原 object,並使用 property shorthand 一次寫入多個 property。
這一切看似美好,唯 ES6 為了效能考慮,...
為 shallow copy,在某些狀況可能不太適用。
Ramda
assoc()
import { assoc } from 'ramda'
let obj = {
price: 100
}
let result = assoc('title')('Speaking JavaScript')(obj) // ?
assoc()
雖為 immutable,但一次只能寫入一個 property 也不方便。
set()
import { lensProp, set } from 'ramda'
let obj = {}
let titleLens = lensProp('title')
let result = set(titleLens)('Speaking JavaScript')(obj) // ?
set()
雖為 immutable,但一次只能寫入一個 property 也不方便。
mix()
import { pipe, clone, mergeDeepRight } from 'ramda'
let mix = pipe(
clone,
mergeDeepRight
)
let obj = {
price: 100
}
let title = 'Speaking JavaScript'
let price = 200
let result = mix(obj)({ title, price }) // ?
第 3 行
let mix = pipe(
clone,
mergeDeepRight
)
第一個 argument 為原 object,使用 Ramda 的 clone()
做 deep copy,並將結果傳給 mergeDeepRight()
的第一個 argument。
第二個 argument 則使用 property shorthand 剛組合的 object,透過 mergeDeepRight()
也做 deep merge,並以右側 object 為主。
Wink-fp
import { mix } from 'wink-fp'
let obj = {
price: 100
}
let title = 'Speaking JavaScript'
let price = 200
let result = mix(obj)({ title, price }) // ?
Wink-fp 已經內建 mix()
可直接使用。
mix()
{ a } -> { b } -> { c }
一次寫入多個 property 並建立全新 object
{ a }
:原 object
{ b }
:想一次寫入多個 property 的 object
{ c }
:合併後全新 object
Conclusion
mix()
看似很神奇,其實只是組合了clone()
與mergeDeepRight()
,這就是 Function Composition 的魅力