本文翻譯自: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 withundefined
只有_.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]))