使用场景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);