javascript中Rest/Spread与Object.assign的不同
ES6中的Rest/Spread使用的很广泛了,
比如简单的(浅)复制一个数组:
const arr1 = [10, 20, 30];
// 复制一下
const copy = [...arr1];
console.log(copy); // [10, 20, 30]
再比如给一个函数传递参数,参数需要一个个地传递,现在参数都在一个数组里面:
const arr = [10, 20, 30]
// 和这行一样 console.log(Math.max(10, 20, 30));
console.log(Math.max(...arr)); // → 30
再比如合并数组:
const arr1 = [10, 20, 30];
const arr2 = [40, 50];
console.log([...arr1,...arr2]); // [10, 20, 30, 40, 50]
不仅对数组,对对象也有类似的操作;
比如复制一个对象的自己的可枚举的属性(own enumerable properties),
const obj1 = {
a: 10,
b: 20
};
const obj2 = {
...obj1,
a: 30
};
console.log(obj2); // → {a: 30, b: 20}
从上面也可以看出,后面属性值的会覆盖前面的属性。再比如合并对象:
const obj1 = {a: 10};
const obj2 = {b: 20};
const obj3 = {c: 30};
console.log({...obj1, ...obj2, ...obj3}); // → {a: 10, b: 20, c: 30}
不过上面的这个功能,用Object.assign也可以实现:
console.log(Object.assign({}, obj1, obj2, obj3)); // → {a: 10, b: 20, c: 30}
不过, spread 和 Object.assign 的效果并不总是一样的:
Object.defineProperty(Object.prototype, 'aa', {
get(value) {
console.log('prototype get aa called!');
return 'prototype aa';
},
set(value) {
console.log('prototype set aa called', value);
}
});
Object.defineProperty(Object.prototype, 'bb', {
get(){
console.log('prototype get bb called!');
return 'prototype bb';
},
set(value) {
console.log('prototype set bb called!', value);
}
});
let source = { };
let target = { };
Object.defineProperty(source, 'b', {
set() {
console.log('source set b');
},
get() {
console.log('source get b');
return 'souce of b';
},
enumerable: true
});
Object.defineProperty(source, 'c', {
set() {
console.log('source set c');
},
get() {
console.log('source get c');
return 'souce of c';
},
enumerable: true
});
Object.defineProperty(source, 'd', {
set() {
console.log('source set d');
},
get() {
console.log('source get d');
return 'souce of d';
},
enumerable: false
});
Object.defineProperty(target, 'a', {
get(){
console.log('target get a');
return 'target of a'
},
set() {
console.log('target set a');
},
enumerable: true
});
Object.defineProperty(target, 'c', {
set(v) {
console.log('target set c,', v);
},
get() {
console.log('target get c');
return 'target of c';
},
enumerable: true
});
console.log('Object.assign(target, source)结果:');
Object.assign(target, source);
console.log('{ ...target, ...source }结果:');
k={ ...target, ...source };
控制台输出:
Object.assign(target, source)结果:
source get b
source get c
target set c, souce of c
{ ...target, ...source }结果:
target get a
target get c
source get b
source get c
直接从MDN复制过来解释吧:
- Object.assign
Properties in the target object will be overwritten by properties in the sources if they have the same key. Later sources’ properties will similarly overwrite earlier ones.
The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties.
- spread
It copies own enumerable properties from a provided object onto a new object.
参考文献
https://css-tricks.com/new-es2018-features-every-javascript-developer-should-know/
上一篇: vector用法
下一篇: 详解C++中 list 与 vector