3

引言

在开发过程中,我们经常能看到 Object.assign 或 Object Spread,这两个方法都能帮助你得到想要的对象。有的人喜欢用Object.assign,有些人喜欢用 Object Spread,那么用哪一种比较好呢?这篇文章就是来探讨这个问题。

Object.assign 与 Object Spread 共同点

功能

都可以实现 object 自有属性(包括 Symbol 属性)的 copy。

示例

创建 MyClass

  class BaseClass {
    foo() { return 1; }
  }
  
  class MyClass extends BaseClass {
    bar() { return 2; }
  }
  
  const obj = new MyClass();
  obj.baz = function() { return 3; };
  obj1[Symbol.for('test')] = 4;

使用 Object Spread

  const clone1 = { ...obj1 };
 
  console.log(clone1); // { baz: [Function], [Symbol(test)]: 4 }
  console.log(clone1.constructor.name); // Object
  console.log(clone1 instanceof MyClassTwo); // false

使用 Object.assign

  const clone2 = Object.assign({},obj1)

  console.log(clone2); // { baz: [Function], [Symbol(test)]: 4 }
  console.log(clone2.constructor.name); // Object
  console.log(clone2 instanceof MyClassTwo); // false

总结

没有把 MyClassBaseClassproperties 赋值给新的对象,说明 只拷贝了object 自有属性(包括 Symbol 属性)。

Object.assign 与 Object Spread 不同点

Object.assign 会触发对象的 setters, Object Spread 不会

触发 target object setters:

class MyClassOne{
    set name(value){
        console.log('set name:', value);
    }
}

const obj = new MyClassOne();

Object.assign(obj, { name:'hahah'}); // Prints "set name: hahah"
const newObj = {...obj,{name:'hahah'}}// Does **not** print

触发 Object.prototype setters:

Object.defineProperty(Object.prototype, 'myProp', {
  set: () => console.log('Setter called');
});

const obj = { myProp: 42 };

Object.assign({}, obj); // Prints "Setter called"
const newObj = { ..obj }; // Does **not** print "Setter called"

替换实现

Object.assign({}, obj) 等于 {...obj}

赋值限制

当你声明了一个对象
const obj = { a:1}
后面需要给这个对象添加属性的时候,Object.assign 可以做到,但是 Spread 方式不行

Object.assign(obj, { b: 2});
console.log(obj); // {a:1, b:2}
// obj = {...obj, b:2} Error: obj is constant

兼容性对比

image.png

image.png

总结

由于 Object.assign 修改了原来的对象,所以会触发原来对象的 setters。而 Object Spread 只是进行了一次浅拷贝,不会触发 setters

总结

  • 这两个方法都是ECMAScript 规范的方法,都可以放心使用。
  • Object.assign 兼容性会更好一点,Object Spread 兼容性也不差。
  • 在兼容性很容易得到处理的今天,为了避免意外触发的 setter,全部使用 Object Spread` 是更好的选择。

参考


specialcoder
2.2k 声望170 粉丝

前端 设计 摄影 文学