一、Rest/Spread 特性
ES2015中添加的最有趣的特性之一是spread操作符。你可以用它替换concat()和slice()方法,使数组的操作(复制、合并)更加简单。
进群:851211580 可获取海量Python学习资料+大牛指导学习
const arr1 = [10, 20, 30];
// make a copy of arr1
const copy = [...arr1];
console.log(copy); // → [10, 20, 30]
const arr2 = [40, 50];
// merge arr2 with arr1
const merge = [...arr1, ...arr2];
console.log(merge); // → [10, 20, 30, 40, 50]
在数组必须以拆解的方式作为函数参数的情况下,spread操作符也很有用。例如:
const arr = [10, 20, 30]
// equivalent to
// console.log(Math.max(10, 20, 30));
console.log(Math.max(...arr)); // → 30
ES2018通过向对象文本添加扩展属性进一步扩展了这种语法。他可以将一个对象的属性拷贝到另一个对象上,参考以下情形:
const obj1 = {
a: 10,
b: 20
};
const obj2 = {
...obj1,
c: 30
};
console.log(obj2); // → {
a: 10, b: 20, c: 30}
在上述代码中,spread操作符遍历obj1属性,并将其添加到obj2的属性中;而在之前的版本中,如此处理会抛出一个异常。需要注意的是,如果存在相同的属性名,只有最后一个会生效。
const obj1 = {
a: 10,
b: 20
};
const obj2 = {
...obj1,
a: 30
};
console.log(obj2); // → {
a: 30, b: 20}
同时,Spread操作符可以作为Object.assign() 的一个替代方案进行对象融合:
const obj1 = {
a: 10};
const obj2 = {
b: 20};
const obj3 = {
c: 30};
// ES2018
console.log({
...obj1, ...obj2, ...obj3}); // → {
a: 10, b: 20, c: 30}
// ES2015
console.log(Object.assign({
}, obj1, obj2, obj3)); // → {
a: 10, b: 20, c: 30}
然而,在进行对象融合时,Spread操作结果并不总是与Object.assign()一致,例如:
Object.defineProperty(Object.prototype, 'a', {
set(value) {
console.log('set called!');``}
});
const obj = {
a: 10};
console.log({
...obj});
// → {
a: 10}
console.log(Object.assign({
}, obj));
// → set called!
// → {
}
在上述代码中,Object.assign()方法继承了setter属性;而spread操作忽略了setter。
划重点:spread只复制枚举属性。在下面的例子中,type属性不会出现在复制对象中,因为它的枚举属性被设置为false:
const car = {
color: 'blue'
Object.defineProperty(car, 'type', {
value: 'coupe',
enumerable: false
});
console.log({
...car}); // → {
color: "blue"}
继承的属性即使是可枚举的也会被忽略:
const car = {
color: 'blue'
};
const car2 = Object.create(car, {
type: {
value: 'coupe',
enumerable: true,
}
});
console.log(car2.color); // → blue`
console.log(car2.hasOwnProperty('color')); // → false
console.log(car2.type); // → coupe
console.log(car2.hasOwnProperty('type'))<