Lodash - .extend() / .assign() 和 .merge() 之间的区别洛达什 版本 3.10.1

2022-08-29 23:05:45

Lodash库中,有人可以提供更好的合并扩展/分配的解释吗?

这是一个简单的问题,但答案仍然回避了我。


答案 1

操作方法如下:对于源中的每个属性,按原样将其值复制到目标。如果属性值本身是对象,则没有对其属性的递归遍历。整个对象将从源中获取并设置为目标。extendassign

工作原理如下:对于源中的每个属性,请检查该属性是否是对象本身。如果是,则以递归方式向下,并尝试将子对象属性从源映射到目标。因此,从本质上讲,我们将对象层次结构从源合并到目标。而对于 /,它只是从源到目标的属性的简单一级副本。mergeextendassign

这里有一个简单的JSBin可以清楚地说明这一点:http://jsbin.com/uXaqIMa/2/edit?js,console

下面是更详细的版本,示例中还包括数组:http://jsbin.com/uXaqIMa/1/edit?js,console


答案 2

洛达什 版本 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是 的别名,因此它们是相同的_.assign
  • 它们似乎都修改了目标对象(第一个参数)
  • 他们都处理相同null

差异

  • _.defaults并与其他参数相比以相反的顺序处理参数(尽管第一个参数仍然是目标对象)_.defaultsDeep
  • _.merge并将合并子对象,其他对象将在根级别覆盖_.defaultsDeep
  • 仅 和 将覆盖具有以下值的值:_.assign_.extendundefined

测试

它们都以类似的方式处理根成员。

_.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"  ]