在Lodash库中,有人能更好地解释合并和扩展/赋值吗?
这是一个简单的问题,但答案还是让我难以回答。
在Lodash库中,有人能更好地解释合并和扩展/赋值吗?
这是一个简单的问题,但答案还是让我难以回答。
下面是扩展/赋值的工作原理:对于源中的每个属性,将其值原样复制到目标。如果属性值本身是对象,则不需要对其属性进行递归遍历。整个对象将从源和设置到目标。
下面是merge的工作原理:对于source中的每个属性,检查该属性是否是对象本身。如果是,则递归向下,并尝试将子对象属性从源映射到目标。所以本质上我们合并了从源到目标的对象层次结构。而对于扩展/赋值,它只是简单地将属性从源复制到目标。
下面是一个简单的JSBin,可以让你清楚地知道: http://jsbin.com/uXaqIMa/2/edit?js,console
下面是更详细的版本,在示例中也包含了数组: http://jsbin.com/uXaqIMa/1/edit?js,console
另一个需要注意的区别是对未定义值的处理:
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不会将未定义值合并为已定义值。
Lodash 3.10.1版本
方法相比
_。merge(客运,[sources],[客户],[thisArg]) _。assigs(物体,[sources],[客户],[thisArg]) _。扩展(物体,[sources],[客户],[thisArg]) _ defaults(物体,(器)。 _ defaultsDeep(物体,(器)。
相似之处
它们都不像您预期的那样适用于数组 _。Extend是_的别名。赋值,所以它们是相同的 它们似乎都修改了目标对象(第一个参数) 它们对空的处理都是一样的
差异
_.defaults和_.defaultsDeep以与其他参数相反的顺序处理参数(尽管第一个参数仍然是目标对象) _。merge和_.defaultsDeep将合并子对象,其他的将在根级覆盖 只有_。赋值和_。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 ({}, { 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" ]
从语义的角度考虑它们的作用可能也会有所帮助:
_.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 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.
我相信,学会从语义的角度来考虑这些方法会让您更好地“猜测”现有值和不存在值的所有不同场景的行为。