乐趣区

关于javascript:Objectassign-object-Spread-运算符

一、两者的定义

1.Object.assign(): Object.assign()办法用于将所有可枚举属性的值从一个过多个源复制到指标对象。它将返回指标对象。

2.开展语法(Spread syntax), 能够在函数调用 / 数组结构时, 将数组表达式或者 string 在语法层面开展;还能够在结构字面量对象时, 将对象表达式按 key-value 的形式开展。

二、两者的用法

1.Object.assign():Object.assign(_target_, …_sources_)

参数

target:指标对象

source:源对象

返回值:指标对象 target

2.开展语法(Spread syntax)

(1)函数调用:
myFunction(...iterableObj);

(2)字面量数组结构或字符串:

[...iterableObj, '4', ...'hello', 6];

(3)结构字面量对象时, 进行克隆或者属性拷贝(ECMAScript 2018 标准新增个性):

let objClone = {...obj};

三、两者的异同

共同点

1. 两者都是去复制旧的对象进而去创立该对象的一个正本,都能够对源对象中可枚举属性进行复制, 能够对 symbols 属性进行复制。

const obj = {foo: 'bar'};
const clone = {...obj};
const clone2 = Object.assign({}, obj);
console.log(clone);
console.log(clone2);

输入:

可见,二者都是复制了源对象的可枚举属性去结构了一个对象正本

2. 二者都是浅拷贝 ,即无论是 Object Spread 运算符还是 Object.assign() 都是只能复制对象的可枚举属性,而不能复制继承的属性和类的属性,然而它们都会复制 ES6 的 symbols 属性

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};
const clone2 = Object.assign({}, obj);

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

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

3. 如果将 null 和 undefined 作为源对象不会报错,然而 null 和 undefined 会被疏忽

  • null 作为 source
const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};
const t = Object.assign({}, x, y);

console.log(z);     //{a: 1, b: 2}
console.log(t);     //{a: 1, b: 2}
  • undefinded 作为 source
const x = {a: 1, b: 2};
const clone = Object.assign(undefined, x);
const clone2 = {undefined, ...x};

console.log(clone);     //TypeError: Cannot convert undefined or null to object
console.log(clone2);        //TypeError: Cannot convert undefined or null to object

5. 如果 null 和 undefined 作为源对象中的属性值,则他们不会被疏忽。

//null 和 undefined 作为 source 外面的 property
const x = {a: null, b: 1, c: 2};
const y = {a: undefined, b: 1, c: 2};

console.log(Object.assign({}, x));    //{a: null, b: 1, c: 2}
console.log(Object.assign({}, y));    //{a: undefined, b: 1, c: 2}

不同点

1. 对于下面的例子,Object.assign()函数基本上能够和 Object spread 操作符调换,object spread spec 明确指出

{… obj}等同于 Object.assign({},obj)。

那么你为什么要应用其中一个呢?一个要害的区别是 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(),你必须确保始终将空对象 {} 作为第一个参数传递。

2. 上面是一个应用 Object.assign()和 in-place 赋值的基准测试(援用自:[[译] Object.assign 和 Object Spread 之争, 用谁?](https://juejin.im/post/5c5d8d…)

const Benchmark = require('benchmark');

const suite = new Benchmark.Suite;

const obj = {foo: 1, bar: 2};

suite.
  add('Object spread', function() {({ baz: 3, ...obj});
  }).
  add('Object.assign()', function() {Object.assign({ baz: 3}, obj);
  }).
  on('cycle', function(event) {console.log(String(event.target));
  }).
  on('complete', function() {console.log('Fastest is' + this.filter('fastest').map('name'));
  }).
  run({'async': true});

在这种状况下,两者是类似的:

Object spread x 3,170,111 ops/sec +-1.50% (90 runs sampled)
Object.assign() x 3,290,165 ops/sec +-1.86% (88 runs sampled)
Fastest is Object.assign()

然而,一旦向 Object.assign()输出一个空对象参数,对象扩大运算符就会更快

suite.
  add('Object spread', function() {({ baz: 3, ...obj});
  }).
  add('Object.assign()', function() {Object.assign({}, obj, {baz: 3});
  })

这是输入:

Object spread x 3,065,831 ops/sec +-2.12% (85 runs sampled)
Object.assign() x 2,461,926 ops/sec +-1.52% (88 runs sampled)
Fastest is Object spread

四、总结

总的来说,Object spread 运算符和 Object.assign()的性能相似,然而 Object spread 运算符在语法上更加简洁,并且比 Object.assign()提供了性能劣势。如果你运行的是 Node.js 8 或更高版本,请尝试应用这些新运算符,使代码更简洁。

退出移动版