展开运算符...传参要求函数支持剩余参数或原生多参数,仅浅拷贝数组,不处理this绑定,解构时剩余元素必须置于末尾。

用 ... 展开数组传参时,函数必须接受可变参数
直接把 [1, 2, 3] 前加 ... 当作参数传给函数,不是所有函数都能接住——关键看它是否支持剩余参数(...args)或原生接受多个独立参数。
- 能用:内置函数如
Math.max(...arr)、console.log(...arr),它们设计上就吃散开的值 - 不能用:比如
parseInt(...arr),它只认第一个参数为字符串,第二个是进制,多余参数被忽略,还可能误把数组第二项当进制数导致NaN - 自定义函数必须显式声明接收方式:
function foo(...args) { }或function foo(a, b, c) { }(且确保数组长度匹配)
... 创建新数组时,浅拷贝陷阱比想象中常见
写 const newArr = [...oldArr] 确实生成了新数组,但只是第一层拷贝。如果原数组里有对象或嵌套数组,引用关系没断开。
- 修改
newArr[0].name会同步影响oldArr[0].name,因为两个数组的第 0 项指向同一个对象 - 想深拷贝?别依赖
...,改用JSON.parse(JSON.stringify(arr))(仅限纯数据)或结构化克隆(structuredClone(arr),现代环境支持) - 合并多个数组时,
[...a, ...b, ...c]没问题,但注意内存:大数组展开会一次性分配新空间,不是懒加载
替代 apply 时,... 不处理 this 绑定
以前用 fn.apply(obj, arr) 是为了指定 this 并传参;现在写 fn(...arr),this 默认是全局或 undefined(严格模式),完全丢失上下文。
- 要保留
this,得配合call或bind:fn.call(obj, ...arr)才等价于旧的apply - 箭头函数没有自己的
this,所以arrowFn.call(obj, ...arr)里的obj会被忽略 - 类方法直接展开调用(
obj.method(...args))是安全的,因为调用时的this由点号左侧决定,和展开无关
在解构赋值里混用 ...,剩余元素必须放最后
写 const [first, ...rest] = arr 没问题,但 const [...front, last] = arr 会报语法错误——剩余元素(...)只能出现在解构模式末尾。
- 想取头尾?用
arr[0]和arr[arr.length - 1]更直白,别硬凑扩展运算符 - 解构对象时也一样:
const { a, ...rest } = obj合法,const { ...rest, a } = obj不合法 - 空数组解构不会报错:
const [...empty] = []得到empty = [],但const [x, ...rest] = []中x是undefined,rest是空数组
实际用的时候,最常掉坑的地方不是语法写错,而是忘了它只做一层展开、不接管 this、也不能倒着解构。这些边界不像报错那么明显,容易埋成静默 bug。










