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度来学习这些方法会让你更好地“猜测”现有和不存在价值的所有不同场景的行为是什么。