.extend()/ .assign()和.merge()之间的区别
在Lodash库中,有人可以更好地解释合并和扩展/分配。
这是一个简单的问题,但答案尽管如此。
以下是extend
/ assign
工作原理:对于源中的每个属性,将其值原样复制到目标。 如果属性值本身是对象,则不会递归遍历它们的属性。 整个对象将从源获取并设置到目的地。
以下是merge
工作原理:对于源代码中的每个属性,检查该属性是否是对象本身。 如果它是递归下去并尝试将子对象属性从源映射到目标。 所以基本上我们合并了从源到目标的对象层次。 而对于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
是一个别名_.assign
,所以它们是相同的 null
一样 差异
_.defaults
和_.defaultsDeep
以相反顺序处理参数(尽管第一个参数仍然是目标对象) _.merge
和_.defaultsDeep
会合并子对象,其他的将在根级别覆盖 _.assign
和_.extend
会覆盖undefined
的值 测试
他们都以类似的方式处理根源的成员。
_.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
值合并到定义的值中。