Lodash - .extend()/ .assign()和.merge()之间的区别

本文翻译自:Lodash - difference between .extend() / .assign() and .merge()

In the Lodash library, can someone provide a better explanation of merge and extend / assign . Lodash库中,有人可以提供合并扩展/分配的更好解释。

Its a simple question but the answer evades me nonetheless. 这是一个简单的问题,但答案却避开了我。


#1楼

参考:https://stackoom.com/question/1Lm1k/Lodash-extend-assign-和-merge-之间的区别


#2楼

Here's how extend / assign works: For each property in source, copy its value as-is to destination. 以下是extend / assign工作原理:对于源中的每个属性,将其值按原样复制到目标。 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. 整个对象将从源中获取并设置到目标。

Here's how merge works: For each property in source, check if that property is object itself. 以下是merge工作原理:对于源中的每个属性,检查该属性是否为对象本身。 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. 对于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


#3楼

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值合并到定义的值中。


#4楼

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])

Similarities 相似

  • None of them work on arrays as you might expect 它们都不像您期望的那样在数组上工作
  • _.extend is an alias for _.assign , so they are identical _.extend是一个别名_.assign ,所以它们是相同的
  • All of them seem to modify the target object (first argument) 所有这些似乎都修改了目标对象(第一个参数)
  • All of them handle null the same 所有这些都处理null相同

Differences 差异

  • _.defaults and _.defaultsDeep processes the arguments in reverse order compared to the others (though the first argument is still the target object) _.defaultsDeep参数相比, _.defaults_.defaultsDeep以相反的顺序处理参数(尽管第一个参数仍然是目标对象)
  • _.merge and _.defaultsDeep will merge child objects and the others will overwrite at the root level _.merge_.defaultsDeep将合并子对象,其他对象将在根级别覆盖
  • Only _.assign and _.extend will overwrite a value with undefined 只有_.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"  ]

#5楼

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 _.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. 我相信从语义的角度学习思考这些方法可以让你更好地“猜测”现有和非现有值的所有不同场景的行为。


#6楼

如果你想要一个没有覆盖的深拷贝,同时保留相同的obj引用

obj = _.assign(obj, _.merge(obj, [source]))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值