使用场景1——拓展数组
let list1 = [1, 2, 3];
let finalList = [...list1, 4];
console.log(finalList); // [ 1, 2, 3, 4 ]
let list1 = [1, 2, 3];
let list2 = [5, 6];
let finalList = [...list1, 4, ...list2];
console.log(finalList); // [ 1, 2, 3, 4, 5, 6 ]
使用场景2——拓展对象
let oldDic = {
a: 1,
};
let newDic = {
...oldDic,
b: 2,
};
console.log(newDic); // { a: 1, b: 2 }
多个对象拓展合并时,若对象的属性相同,则后拓展的对象属性值会覆盖之前的对象属性值。
let oldDic = {
name: "旧名字",
};
let newDic = {
name: "新名字",
};
let finalDic = {
...oldDic,
...newDic,
};
console.log(finalDic); // 得到 { name: '新名字' }
借助多对象拓展属性覆盖的特点,给参数赋默认值,以查询列表为例:
// 默认参数值
let defaultParams = {
name: "默认查询的名称",
pageIndex: 1,
pageSize: 10,
};
// 页面传入的参数值
let currentParams = {
name: "本次查询的名字",
pageIndex: 4,
};
// 最终查询的参数值
let finalParams = {
...defaultParams,
...currentParams,
};
console.log(finalParams);
打印结果
{
name: '本次查询的名字',
pageIndex: 4,
pageSize: 10
}
使用场景3——函数多参数传递
let data = [1, 2];
function sum(a, b) {
return a + b;
}
let result = sum(...data);
console.log(result);
不使用扩展运算符的写法为:
let data = [1, 2];
function sum(a, b) {
return a + b;
}
let result = sum(data[0], data[1]);
console.log(result);
可见使用扩展运算符更方便
使用场景4——解构赋值
与解构配合时,扩展运算符只能用在最后一个上
let [a, b, ...list] = [1, 2, 3, 4, 5, 6];
console.log(a); // 1
console.log(b); // 2
console.log(list); // [ 3, 4, 5, 6 ]
实现原理
将实现了Iterator 接口的对象中的每个元素一个个迭代取出单独使用。
因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,如Set,Map,生成器
let set1 = new Set()
set1.add(1)
set1.add(2)
console.log(...set1) // 1 2
let map1 = new Map();
map1.set('k1', 1);
map1.set('k2', 2);
console.log(...map1) // [ 'k1', 1 ] [ 'k2', 2 ]
let go = function* () {
yield 1;
yield 2;
yield 3;
};
console.log(...go());
错误的用法
只有函数调用时,扩展运算符才可以放在圆括号中,否则会报错。
(...[1, 2])
// Uncaught SyntaxError: Unexpected number
对象不是Iterator接口实现,所以不能直接拓展
// 会报错 Found non-callable @@iterator
console.log(
...{
a: 1,
b: 2,
}
);
// 没有报错,但什么都不会打印
let dic = {
a: 1,
b: 2,
};
console.log(...dic);