Lodash – .extend()/ .assign()和.merge()之间的区别
在Lodash库中,有人可以提供合并和扩展/分配的更好的解释。
这是一个简单的问题,但答案回避我。
以下是extend
/ assign
工作原理:对于源中的每个属性,将其值原样复制到目标。 如果属性值本身是对象,则不会recursion遍历它们的属性。 整个对象将从源获取并设置到目的地。
以下是merge
工作原理:对于源代码中的每个属性,检查该属性是否是对象本身。 如果它是recursion下来,并尝试将源对象的子对象属性映射。 所以基本上我们合并了从源到目标的对象层次。 而对于extend
/ assign
,它是从源到目的地的简单属性级别的副本。
这里是简单的JSBin,这将使这清澈见底: http ://jsbin.com/uXaqIMa/2/edit?js, console
下面是更详细的版本,其中包括数组在示例中: http : //jsbin.com/uXaqIMa/1/edit?js,console
Lodash版本3.10.1
方法比较
-
_.merge(object, [sources], [customizer], [thisArg])
-
_.assign(object, [sources], [customizer], [thisArg])
-
_.extend(object, [sources], [customizer], [thisArg])
-
_.defaults(object, [sources])
-
_.defaultsDeep(object, [sources])
相似
- 他们没有一个像你所期望的那样在数组上工作
-
_.extend
是_.extend
的别名,所以它们是相同的 - 他们都似乎修改目标对象(第一个参数)
- 他们都处理
null
一样
差异
-
_.defaults
和_.defaultsDeep
处理参数的顺序与其他顺序相反(尽pipe第一个参数仍然是目标对象) -
_.merge
和_.defaultsDeep
将合并子对象,其他的将在根级别覆盖 - 只有
_.assign
和_.extend
会覆盖undefined
的值
testing
他们都以类似的方式处理根源的成员。
_.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
句柄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" }
他们都处理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 }
但只有_.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" }}
而他们都不会合并数组看起来
_.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" ] }
全部修改目标对象
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" }
数组没有真正的工作
注意:正如@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" ]
要注意的另一个区别是处理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}
所以merge
不会将undefined
值合并到定义的值中。
从语义的angular度考虑他们做了什么也许是有帮助的:
_。分配
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 is like assign but does not assign objects but replicates them instead. (deep copy)
_.defaults
provides default values for missing values. so will assign only values for keys that do not exist yet in the source.
_.defaultsDeep
works like _defaults but like merge will not simply copy objects and will use recursion instead.
我相信,从语义的angular度来学习这些方法会让你更好地“猜测”现有和不存在价值的所有不同场景的行为是什么。