展开运算符和object.assign()的区别

Object Spread 和 Object.assign 在功能上很相似。你应该使用哪一个? 事实证明,答案比你想象的要微妙许多。

Object Spread 概论

object Spread 运算符的基本思想是使用现有对象自身属性来创建普通对象。所以{…obj}创建一个和obj具有相同属性的对象。对于一个普通的旧对象,你实际上在创建一个obj的副本。


const obj = { foo: 'bar' };
const clone = { ...obj }; // `{ foo: 'bar' }`
obj.foo = 'baz';
clone === obj //false

与object.assign()类似。扩展运算符(Object spread)不复制继承的属性或类的属性,但是它会复制ES6的 symbols 属性
object.assign() [fn(target,…sorce)]


class BaseClass {
  foo() { return 1; }
}
 
class MyClass extends BaseClass {
  bar() { return 2; }
}
 
const obj = new MyClass();
obj.baz = function() { return 3; };
obj[Symbol.for('test')] = 4;
 
// Does _not_ copy any properties from `MyClass` or `BaseClass`
const clone = { ...obj };
 
console.log(clone); // { baz: [Function], [Symbol(test)]: 4 }
console.log(clone.constructor.name); // Object
console.log(clone instanceof MyClass); // false

还可以使用 Object spread 操作符混合其他属性。
顺序问题: Object spread 操作符将覆盖在它之前定义的属性

const obj = { a: 'a', b: 'b', c: 'c' };
{ a: 1, b: null, c: void 0, ...obj }; // { a: 'a', b: 'b', c: 'c' }
{ a: 1, b: null, ...obj, c: void 0 }; // { a: 'a', b: 'b', c: undefined }
{ a: 1, ...obj, b: null, c: void 0 }; // { a: 'a', b: null, c: undefined }
{ ...obj, a: 1, b: null, c: void 0 }; // { a: 1, b: null, c: undefined }

和 Object.assign() 的区别

对于上面的例子,Object.assign()函数基本上可以与 Object spread 操作符互换。事实上,object spread spec 明确指出{… obj}等同于Object.assign({},obj)。

const obj = { foo: 'bar' }; 
const clone =  Object.assign({},obj); 
obj===clone //false
const obj = { foo: 'bar' }; 
const clone =  Object.assign(obj); 
obj===clone //true


const obj = { a: 'a', b: 'b', c: 'c' };
Object.assign({ a: 1, b: null, c: void 0 }, obj); // { a: 'a', b: 'b', c: 'c' }
Object.assign({ a: 1, b: null }, obj, { c: void 0 }); // { a: 'a', b: 'b', c: undefined }
Object.assign({ a: 1 }, obj, { b: null, c: void 0 }); // { a: 'a', b: null, c: undefined }
Object.assign({}, obj, { a: 1, b: null, c: void 0 }); // { a: 1, b: null, c: undefined }

那么你为什么要使用其中一个呢?一个关键的区别是 Object spread 操作符总是给你一个POJO(Plain Ordinary JavaScript Object)。而Object.assign()函数却修改其第一个传入对象obj:


class MyClass {
  set val(v) {
    console.log('Setter called', v);
    return v;
  }
}
const obj = new MyClass();
 
Object.assign(obj, { val: 42 }); // Prints "Setter called 42"

换句话说,Object.assign()修改了一个对象,因此它可以触发 ES6 setter。如果你更喜欢使用immutable技术,那么 Object spread 操作符就是你更好的选择。使用 Object.assign(),你必须确保始终将空对象{​​}作为第一个参数传递。

当一个 Object 使用了 Object.defineProperty 修改了 set 方法,因为调用 Object.assign 会触发 setter 方法,会触发意想不到的错误。

最后

Object rest / spread运算符在语法更加简洁,并且比Object.assign()提供了性能优势。 如果你运行的是Node.js 8或更高版本,请尝试使用这些新运算符,使代码更简洁。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值