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

在Lodash库中,有人可以更好地解释合并和扩展/分配。

这是一个简单的问题,但答案尽管如此。


以下是extend / assign工作原理:对于源中的每个属性,将其值原样复制到目标。 如果属性值本身是对象,则不会递归遍历它们的属性。 整个对象将从源获取并设置到目的地。

以下是merge工作原理:对于源代码中的每个属性,检查该属性是否是对象本身。 如果它是递归下去并尝试将子对象属性从源映射到目标。 所以基本上我们合并了从源到目标的对象层次。 而对于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是一个别名_.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"  ]
    

    要注意的另一个区别是处理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值合并到定义的值中。

    链接地址: http://www.djcxy.com/p/27669.html

    上一篇: difference between .extend() / .assign() and .merge()

    下一篇: Node peerDependencies Errors With Grunt