點燈坊

失くすものさえない今が強くなるチャンスよ

如何 Merge Object ?

Sam Xiao's Avatar 2019-08-16

初學者常直覺將 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。

merge000

回傳為不預期結果,因此不能使用 +

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。

merge001

Spread Operator

let obj1 = { firstName: 'Sam' };
let obj2 = { lastName: 'Xiao'};

let obj3 = {...obj1, ...obj2 }; // ?

ES6 可在 {} 內使用 ... 將 property 展開,中間加上 , 即可合併 object。

merge002

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()

merge003

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()