【发布时间】:2023-03-23 14:21:01
【问题描述】:
在Lodash 库中,有人可以对merge 和extend / assign 提供更好的解释。
这是一个简单的问题,但答案却让我回避了。
【问题讨论】:
标签: javascript lodash
在Lodash 库中,有人可以对merge 和extend / assign 提供更好的解释。
这是一个简单的问题,但答案却让我回避了。
【问题讨论】:
标签: javascript lodash
如果您想要一个没有覆盖的深层副本,同时保留相同的 obj 参考
obj = _.assign(obj, _.merge(obj, [source]))
【讨论】:
_.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" ]
【讨论】:
_.extend is an alias for _.assign, so they are identical 与 Only _.assign will overwrite a value with undefined 冲突
从语义的角度考虑它们的作用也可能会有所帮助:
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)
provides default values for missing values.
so will assign only values for keys that do not exist yet in the source.
works like _defaults but like merge will not simply copy objects
and will use recursion instead.
我相信,学习从语义的角度思考这些方法可以让您更好地“猜测”现有和非现有值的所有不同场景的行为。
【讨论】:
extend/assign 的工作原理如下:对于源中的每个属性,将其值原样复制到目标。如果属性值本身是对象,则不会递归遍历它们的属性。整个对象将从源获取并设置到目标。
merge 的工作原理如下:对于源中的每个属性,检查该属性是否是对象本身。如果是,则递归下去并尝试将子对象属性从源映射到目标。所以本质上我们将对象层次结构从源合并到目标。而对于extend/assign,它是从源到目标的简单的一级属性副本。
这里有一个简单的 JSBin,可以让这一切变得一清二楚: http://jsbin.com/uXaqIMa/2/edit?js,console
下面是更详细的版本,示例中也包含数组: http://jsbin.com/uXaqIMa/1/edit?js,console
【讨论】:
var combined = merge({}, src, dest)
另一个需要注意的区别是处理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 值合并到定义的值中。
【讨论】:
mergeInto 具有toMerge 没有的属性,那么它将保留这些属性。在那种情况下,它就不是克隆了。