初學者常直覺將 Object 如 String 以 +
合併,但 Object 須以特殊方式才能合併。
Version
macOS Mojave 10.14.5
VS Code 1.37.0
Quokka 1.0.240
ECMAScript 2015
Ramda 0.26.1
Plus Operator
let obj1 = { firstName: 'Sam' };
let obj2 = { lastName: 'Xiao' };
let obj3 = obj1 + obj2; // ?
直覺會使用 +
plus operator。
回傳為不預期結果,因此不能使用 +
。
Object.assign()
import { equals } from 'ramda';
let obj1 = { firstName: 'Sam' };
let obj2 = { lastName: 'Xiao' };
let obj3 = Object.assign({}, obj1, obj2); // ?
在 ES5 若要 merge object,必須使用 Object.assign()
。
Object.assign(target, …sources)
將 source object merge 到 target object
target
:target object
...sources
:source object,可包含多個 object
Object.assign()
原本是 merge object,所以第一個 argument 為 target object,若 target object 為 {}
,其行為剛好等於 clone object。
其中 sources
前有 ...
,表示可接受無限 source object。
Spread Operator
let obj1 = { firstName: 'Sam' };
let obj2 = { lastName: 'Xiao'};
let obj3 = {...obj1, ...obj2 }; // ?
ES6 可在 {}
內使用 ...
將 property 展開,中間加上 ,
即可合併 object。
Ramda
import { merge, mergeRight } from 'ramda';
let obj1 = { firstName: 'Sam' };
let obj2 = { lastName: 'Xiao'};
let obj3 = merge(obj1, obj2); // ?
let obj4 = mergeRight(obj1, obj2); // ?
Ramda 也提供了 merge()
與 mergeRight()
合併 object,功能與 Object.assign()
一樣。
merge()
{k: v} -> {k: v} -> {k: v}
將兩個 object 合併,若 property 相同,則第二個 object 的 property 會蓋掉第一個 object
{k: v}
:第一個 object
{k: v}
:第二個 object
{k: v}
:回傳合併後的 object
mergeRight()
{k: v} -> {k: v} -> {k: v}
將兩個 object 合併,若 property 相同,則第二個 object 的 property 蓋掉第一個 object
{k: v}
:第一個 object
{k: v}
:第二個 object
{k: v}
:回傳合併後的 object
事實上
merge()
與mergeRight()
底層也是由Object.assign()
實作,也因為merge()
與mergeRight()
功能完全相同,但merge()
已經被官網列為deprecated
,建議使用mergeRight()
取代merge()
Conclusion
- clone 還有分 shallow clone 與 deep clone,但 merge 都只有 shallow merge 而以,因此 Ramda 的
merge()
並沒有太大優勢,只剩下 function 名稱可讀性較佳與 curried function 而已
Reference
MDN, object.assign()
MDN, Spread syntax
Ramda, merge()
Ramda, mergeRight()