1. 使用语法
展开运算符(Spread Operator)(...
)是JavaScript的ES6引入的一个重要特性,展开运算符极大地简化了JavaScript中数组和对象的操作,是现代JavaScript开发中不可或缺的特性之一。
展开运算符由三个英文句号(...
)组成,可以应用于:
- 可迭代对象(数组、字符串、Map、Set等)
- 对象字面量(Object)(ES2018引入)
它允许将一个可迭代对象在函数调用/数组构造时展开,或者将对象表达式在对象构造时展开。
示例可见使用场景,要注意一些使用事项,见最后的注意事项。
2. 工作原理
展开运算符的工作原理基于迭代器协议。当使用...
时,JavaScript引擎会:
- 检查对象是否实现了
Symbol.iterator
方法 - 如果实现了,调用该方法获取迭代器
- 遍历迭代器,将每个元素“展开”到当前位置
示例:
const arr = [1, 2, 3];
console.log(...arr); // 相当于 console.log(arr[0], arr[1], arr[2]);
const obj = { a: 1, b: 2 };
const newObj = { ...obj, c: 3 }; // { a: 1, b: 3, c: 4 }
3. 常用场景
-
函数调用中的展开
// 不使用展开运算符 Math.max(1, 2, 3); // 3 Math.max([1, 2, 3]); // NaN // 使用展开运算符 Math.max(...[1, 2, 3]); // 3 // 等同于 Math.max(1, 2, 3)
-
数组字面量中的展开
const arr1 = [1, 2, 3]; const arr2 = [...arr1, 4, 5, 6]; // [1, 2, 3, 4, 5, 6]
-
对象字面量中的展开(ES2018引入)
const obj1 = { foo: 'bar', x: 42 }; const obj2 = { ...obj1, y: 13 }; // { foo: 'bar', x: 42, y: 13 }
4. 注意事项
-
浅拷贝:展开运算符执行的是浅拷贝,对于嵌套对象或数组,只会复制引用
const nested = { a: { b: 1 } }; const copy = { ...nested }; copy.a.b = 2; console.log(nested.a.b); // 2 (原始对象也被修改)
-
对象只能在{}中展开:对象不能直接展开,必须在{}中使用
-
对象展开顺序:后面的属性会覆盖前面的同名属性
const obj = { a: 1, b: 2 }; const newObj = { ...obj, a: 3 }; // { a: 3, b: 2 }
-
用于非指定的对象(迭代变量或对象)的展开会自动转为对象
console.log({ ...1 }); // 相当于console.log({ ...new Object(1)}) console.log({ ...null }); // 相当于console.log({ ...new Object(null)}) console.log([...null]); // 报错;展开对象,就必须在{}中展开
-
不可枚举属性:展开运算符不会复制对象的不可枚举属性
-
展开运算符不会复制对象的原型链