Lodash - .extend()/ .assign()和.merge()之間的區別

本文翻譯自:Lodash - difference between .extend() / .assign() and .merge()

In the Lodash library, can someone provide a better explanation of merge and extend / assign . Lodash庫中,有人可以提供合併擴展/分配的更好解釋。

Its a simple question but the answer evades me nonetheless. 這是一個簡單的問題,但答案卻避開了我。


#1樓

參考:https://stackoom.com/question/1Lm1k/Lodash-extend-assign-和-merge-之間的區別


#2樓

Here's how extend / assign works: For each property in source, copy its value as-is to destination. 以下是extend / assign工作原理:對於源中的每個屬性,將其值按原樣複製到目標。 if property values themselves are objects, there is no recursive traversal of their properties. 如果屬性值本身是對象,則不會對其屬性進行遞歸遍歷。 Entire object would be taken from source and set in to destination. 整個對象將從源中獲取並設置到目標。

Here's how merge works: For each property in source, check if that property is object itself. 以下是merge工作原理:對於源中的每個屬性,檢查該屬性是否爲對象本身。 If it is then go down recursively and try to map child object properties from source to destination. 如果它然後遞歸下去並嘗試將子對象屬性從源映射到目標。 So essentially we merge object hierarchy from source to destination. 基本上我們將對象層次結構從源合併到目標。 While for extend / assign , it's simple one level copy of properties from source to destination. 對於extend / assign ,它是從源到目標的簡單的一級屬性副本。

Here's simple JSBin that would make this crystal clear: http://jsbin.com/uXaqIMa/2/edit?js,console 這裏有簡單的JSBin,可以清晰地表達這一點: http ://jsbin.com/uXaqIMa/2/edit?js, console

Here's more elaborate version that includes array in the example as well: http://jsbin.com/uXaqIMa/1/edit?js,console 這裏有更復雜的版本,包括示例中的數組: http//jsbin.com/uXaqIMa/1/edit?js,console


#3樓

Another difference to pay attention to is handling of undefined values: 要注意的另一個不同之處是處理undefined值:

mergeInto = { a: 1}
toMerge = {a : undefined, b:undefined}
lodash.extend({}, mergeInto, toMerge) // => {a: undefined, b:undefined}
lodash.merge({}, mergeInto, toMerge)  // => {a: 1, b:undefined}

So merge will not merge undefined values into defined values. 因此merge不會將undefined值合併到定義的值中。


#4樓

Lodash version 3.10.1 Lodash版本3.10.1

Methods compared 方法比較

  • _.merge(object, [sources], [customizer], [thisArg])
  • _.assign(object, [sources], [customizer], [thisArg])
  • _.extend(object, [sources], [customizer], [thisArg])
  • _.defaults(object, [sources])
  • _.defaultsDeep(object, [sources])

Similarities 相似

  • None of them work on arrays as you might expect 它們都不像您期望的那樣在數組上工作
  • _.extend is an alias for _.assign , so they are identical _.extend是一個別名_.assign ,所以它們是相同的
  • All of them seem to modify the target object (first argument) 所有這些似乎都修改了目標對象(第一個參數)
  • All of them handle null the same 所有這些都處理null相同

Differences 差異

  • _.defaults and _.defaultsDeep processes the arguments in reverse order compared to the others (though the first argument is still the target object) _.defaultsDeep參數相比, _.defaults_.defaultsDeep以相反的順序處理參數(儘管第一個參數仍然是目標對象)
  • _.merge and _.defaultsDeep will merge child objects and the others will overwrite at the root level _.merge_.defaultsDeep將合併子對象,其他對象將在根級別覆蓋
  • Only _.assign and _.extend will overwrite a value with undefined 只有_.assign_.extend將覆蓋undefined的值

Tests 測試

They all handle members at the root in similar ways. 它們都以類似的方式處理根目錄中的成員。

_.assign      ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.merge       ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.defaults    ({}, { a: 'a' }, { a: 'bb' }) // => { a: "a"  }
_.defaultsDeep({}, { a: 'a' }, { a: 'bb' }) // => { a: "a"  }

_.assign handles undefined but the others will skip it _.assign處理undefined但其他人將跳過它

_.assign      ({}, { a: 'a'  }, { a: undefined }) // => { a: undefined }
_.merge       ({}, { a: 'a'  }, { a: undefined }) // => { a: "a" }
_.defaults    ({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }
_.defaultsDeep({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }

They all handle null the same 它們都處理null相同

_.assign      ({}, { a: 'a'  }, { a: null }) // => { a: null }
_.merge       ({}, { a: 'a'  }, { a: null }) // => { a: null }
_.defaults    ({}, { a: null }, { a: 'bb' }) // => { a: null }
_.defaultsDeep({}, { a: null }, { a: 'bb' }) // => { a: null }

But only _.merge and _.defaultsDeep will merge child objects 但只有_.merge_.defaultsDeep纔會合併子對象

_.assign      ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "b": "bb" }}
_.merge       ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}
_.defaults    ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a" }}
_.defaultsDeep({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}

And none of them will merge arrays it seems 它們似乎都沒有合併數組

_.assign      ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.merge       ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.defaults    ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a"  ] }
_.defaultsDeep({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a"  ] }

All modify the target object 全部修改目標對象

a={a:'a'}; _.assign      (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.merge       (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaults    (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaultsDeep(a, {b:'bb'}); // a => { a: "a", b: "bb" }

None really work as expected on arrays 沒有真正按預期在陣列上工作

Note: As @Mistic pointed out, Lodash treats arrays as objects where the keys are the index into the array. 注意:正如@Mistic指出的那樣,Lodash將數組視爲對象,其中鍵是數組的索引。

_.assign      ([], ['a'], ['bb']) // => [ "bb" ]
_.merge       ([], ['a'], ['bb']) // => [ "bb" ]
_.defaults    ([], ['a'], ['bb']) // => [ "a"  ]
_.defaultsDeep([], ['a'], ['bb']) // => [ "a"  ]

_.assign      ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.merge       ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.defaults    ([], ['a','b'], ['bb']) // => [ "a", "b"  ]
_.defaultsDeep([], ['a','b'], ['bb']) // => [ "a", "b"  ]

#5樓

It might be also helpful to consider what they do from a semantic point of view: 從語義的角度考慮它們的作用可能也是有幫助的:

_.assign _。分配

   will assign the values of the properties of its second parameter and so on,
   as properties with the same name of the first parameter. (shallow copy & override)

_.merge _。合併

   merge is like assign but does not assign objects but replicates them instead.
  (deep copy)

_.defaults _.defaults

   provides default values for missing values.
   so will assign only values for keys that do not exist yet in the source.

_.defaultsDeep _.defaultsDeep

   works like _defaults but like merge will not simply copy objects
   and will use recursion instead.

I believe that learning to think of those methods from the semantic point of view would let you better "guess" what would be the behavior for all the different scenarios of existing and non existing values. 我相信從語義的角度學習思考這些方法可以讓你更好地“猜測”現有和非現有值的所有不同場景的行爲。


#6樓

如果你想要一個沒有覆蓋的深拷貝,同時保留相同的obj引用

obj = _.assign(obj, _.merge(obj, [source]))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章