javascript Lodash - .extend() / .assign() 和 .merge() 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19965844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Lodash - difference between .extend() / .assign() and .merge()
提问by JDillon522
回答by Shital Shah
Here's how extend
/assign
works: For each property in source, copy its value as-is to destination. 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.
以下是extend
/ 的assign
工作原理:对于源中的每个属性,将其值按原样复制到目标。如果属性值本身是对象,则不会递归遍历它们的属性。整个对象将从源中取出并设置到目标中。
Here's how merge
works: For each property in source, check if that property is object itself. 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.
下面是如何merge
工作的:对于源的每个属性,检查如果该属性是对象本身。如果是,则递归向下并尝试将子对象属性从源映射到目标。所以本质上我们合并了从源到目标的对象层次结构。而对于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
回答by Nate
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])
_.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- All of them seem to modify the target object (first argument)
- All of them handle
null
the same
- 它们都不能像您期望的那样在数组上工作
_.extend
是 的别名_.assign
,所以它们是相同的- 他们似乎都在修改目标对象(第一个参数)
- 他们都处理
null
相同的
Differences
差异
_.defaults
and_.defaultsDeep
processes the arguments in reverse order compared to the others (though the first argument is still the target object)_.merge
and_.defaultsDeep
will merge child objects and the others will overwrite at the root level- Only
_.assign
and_.extend
will overwrite a value withundefined
_.defaults
并_.defaultsDeep
以与其他参数相反的顺序处理参数(尽管第一个参数仍然是目标对象)_.merge
并且_.defaultsDeep
将合并子对象和其他人将在根级别覆盖- 只有
_.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" ]
回答by samz
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
值合并为定义的值。
回答by epeleg
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
_.默认值
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.
我相信学习从语义的角度思考这些方法会让你更好地“猜测”存在和不存在值的所有不同场景的行为。
回答by mbao01
If you want a deep copy without override while retaining the same obj
reference
如果您想要一个没有覆盖的深层复制同时保留相同的obj
引用
obj = _.assign(obj, _.merge(obj, [source]))
obj = _.assign(obj, _.merge(obj, [source]))