... 是什么它不是函数也不是方法,而是一种语法糖,用于把可迭代对象(如数组、字符串、类数组)或对象“展开”成独立的元素。本质是把一个整体“打散”,让内部项能被直接使用。
... 合并或浅拷贝常见于合并多个数组、给函数传参、快速复制数组。注意:只做一层浅拷贝,嵌套数组/对象仍共享引用。
[...arr1, ...arr2]
Math.max(...numbers),比 Math.max.apply(null, numbers) 更直观const newArr = [...oldArr],比 oldArr.slice() 或 Array.from(oldArr) 更简洁[...null] 或 [...undefined] 会直接报错 TypeError: null is not iterable
... 解构与合并只能用于对象字面量中,且必须在最后一个位置;用于提取已有属性或合并多个对象。不能像数组那样用在函数参数里(那是剩余参数,语法相同但语义不同)。
{ ...obj1, ...obj2 },后者属性覆盖前者(同名 key)const { a, b, ...rest } = obj,rest 是不含 a、b 的新对象{ ...obj1, x: 1, ...obj2 } 中,obj2 会覆盖 x: 1,因为后写的生效null 或 undefined:{ ...null } 报错 TypeError: Cannot spread non-iterable null
... 容易混淆的点写法一样,但出现位置和作用完全不同:扩展运算符在「等号右侧」或「函数调用时」,用于展开;剩余参数在「函数参数列表末尾」或「解构左侧」,用于收集成数组。
fn(...arr)、[...arr]、{...obj}
function fn(a, b, ...rest) {}
、const [a, b, ...rest] = arr
const [first, ...others] = [...arr] —— 右边是扩展,左边是剩余const { a, ...rest } = obj 合法,但 function fn({ a, ...rest }) {} 会语法报错const arr = [1, 2];
console.log(...arr); // 1 2
console.log([...arr, 3]); // [1, 2, 3]
const obj = { a: 1, b: 2 };
console.log({ ...obj, c: 3 }); // { a: 1, b: 2, c: 3 }
const { a, ...rest } = obj;
console.log(rest); // { b: 2 }
真正容易出问题的地方不在语法,而在误以为 ... 能深拷贝、能展开非可迭代值、或混淆它和剩余参数的上下文。写之前先看清楚它在等号哪一边、在函数定义还是调用里。