对象的合并 Object.assign、JQuery、lodash、Immutable

ES

Object.assign(target, ...sources)

  1. 相同属性名且属性值是对象时,浅拷贝。
  2. 只会拷贝源对象自身的并且可枚举的属性到目标对象身上。
  3. target 后的参数,都合并到 target 上。
Object.assign(
  {},
  { a: 1 },
  { b: { c: 2, d: 3 } },
  { b: { e: 4 } }
)
// { a: 1, b: { e: 4 } }

JQuery

$.extend([deep], target, object1, [objectN])

  1. deep 布尔值,默认为 false,传 true 时,遇到相同属性名且属性值是对象时,会合并属性值(深拷贝)。
  2. target 后的参数,都合并到 target 上。
var object1 = { apple: 0, banana: {weight: 52, price: 100}, cherry: 97};
var object2 = { banana: {price: 200}, durian: 100};

// 修改原来的对象
$.extend(object1, object2);
// {apple: 0, banana: {price: 200}, cherry: 97, durian: 100}
object1 === {apple: 0, banana: {price: 200}, cherry: 97, durian: 100} // true

//合并对象到empty中,不会破坏原来的对象(object1)。
var empty = {}
var object = $.extend(empty, object1, object2);
empty === {apple: 0, banana: {price: 200}, cherry: 97, durian: 100} // true
object === empty // true

// 合并属性值
$.extend(true, {}, object1, object2); 
// {apple: 0, banana: {weight: 52, price: 200}, cherry: 97, durian: 100}

lodash

assign

  1. 会忽略原型链上的属性。
  2. 会修改原来的对象。

把源对象(sources)的属性分配到目标对象(object),源对象会从左往右地调用,后面对象的属性会覆盖前面的。

assign(
  {},
  { a: 1 },
  { b: { c: 2, d: 3 } },
  { b: { e: 4 } }
)
// { a: 1, b: { e: 4 } }

// 忽略原型链上的属性
function Foo() { this.c = 3; }
Foo.prototype.d = 4;
assign({ a: 1 }, new Foo());
// { a: 1, c: 3 }

// 会修改原来的对象
var test = { a: 1 };
assign(test, { b: 2 }); // { a: 1, b: 2 }
console.log(test);      // { a: 1, b: 2 }

extend

  1. 会把原型链上的属性合并到目标对象。
  2. 会修改原来的对象。

在 3.x 版本中,extendassign 的别名,它们的作用是一模一样的。
在 4.x 版本中,extendassignIn 的别名,和 assign 有点区别。

// 把源对象原型链上的属性也合并到目标对象上
function Foo() { this.c = 3; }
Foo.prototype.d = 4;
extend({ a: 1 }, new Foo());
// { a: 1, c: 3, d: 4 }

merge

  1. 相同属性名且属性值是对象时,深拷贝。
  2. 会修改原来的对象。

merge 也和 assign 类似,不同的地方在于 merge 遇到相同属性的时候,如果属性值为纯对象(plain object)或者集合(collection)时,不是用后面的属性值去覆盖前面的属性值,而是会把前后两个属性值合并。如果源对象的属性值为 undefined,则会忽略该属性。会修改原来的对象。

merge(
  {},
  { a: 1 },
  { b: { c: 2, d: 3} },
  { b: { e: 4 } }
)
// { a: 1, b: { c: 2, d: 3, e: 4 } }

Immutable

merge

  1. 不会修改原来的对象。
  2. 相同属性名且属性值是对象时,浅拷贝。
Immutable.merge(
  {},
  { a: 1 },
  { b: { c: 2, d: 3 } },
  { b: { e: 4 } }
)
// { a: 1, b: { e: 4 } }

mergeDeep

  1. 不会修改原来的对象。
  2. 相同属性名且属性值是对象时,深拷贝。
Immutable.mergeDeep(
  {},
  { a: 1 },
  { b: { c: 2, d: 3} },
  { b: { e: 4 } }
)
// { a: 1, b: { c: 2, d: 3, e: 4 } }

性能对比

对象合并,循环 10,000次,耗时对比。

浅拷贝

ES: 6 ms (Object.assign)
Jquery: 6 ms ($.extend(false, target, object1, [objectN]))
lodash: 10 ms (assign、extend)
Immutable: 211 ms (merge)

深拷贝

Jquery: 26 ms ($.extend(true, target, object1, [objectN]))
lodash: 41 ms (merge)
Immutable: 247 ms (mergeDeep)

知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。