剩余运算符在数组解构中必须置于末尾且紧邻变量名,如[first, ...rest] = arr;不可写成[a, ...rest, b]等非法形式;其作用是按序收集剩余元素为数组,严格保留稀疏数组中的undefined。

剩余运算符在数组解构中怎么写才有效
必须把 ... 放在解构模式的**末尾**,且紧挨着一个变量名,不能有逗号或其它元素跟在后面。否则语法报错:SyntaxError: Rest element must be last element。
常见错误是写成 [a, ..., b] = arr 或 [a, ...rest, b] = arr —— 这两种都非法,JS 引擎直接拒绝解析。
-
[first, ...rest] = [1, 2, 3, 4]→first是1,rest是[2, 3, 4] -
[a, b, ...rest] = ['x', 'y']→a是'x',b是'y',rest是空数组[] -
[...rest] = [10]→rest是[10],等价于浅拷贝原数组
为什么 rest 元素一定是数组,哪怕右边是类数组或字符串
数组解构中的 ... 不是“展开”,而是“收集”——它会把剩余项按顺序放进一个新数组,不管源值是否可迭代。遇到字符串时也会逐字符收进数组(因为字符串是可迭代的)。
-
[...chars] = 'hi'→chars是['h', 'i'] -
[head, ...tail] = new Set([1, 2, 3])→head是1,tail是[2, 3](Set可迭代) - 但
[...rest] = {0: 'a', 1: 'b', length: 2}会失败,因为普通对象不可迭代;需先用Array.from()或扩展运算符转成数组再解构
和函数剩余参数的 rest 写法看起来一样,但行为不完全等价
函数参数里的 function f(a, ...rest) {} 中的 rest 总是数组,且忽略 undefined 或空位;而数组解构的 ... 严格按索引位置取值,会保留稀疏数组中的空位(即 undefined)。
-
[a, ...rest] = [1, , 3]→a是1,rest是[undefined, 3](注意第二个元素是undefined,不是被跳过) - 但
function f(x, ...args) { return args; }; f(1, , 3)中,args是[3](函数调用时省略参数不产生undefined,传参时写两个逗号等于只传了第一个和第三个) - 所以别假设两者行为对称;数组解构的
...是“按序切片”,不是“过滤后收集”
性能和兼容性要注意什么
现代浏览器和 Node.js(≥ v8.3)都支持,但 IE 完全不支持。如果需兼容旧环境,得用 slice() 模拟:
const arr = [1, 2, 3, 4]; const first = arr[0]; const rest = arr.slice(1); // 替代 [first, ...rest] = arr
另外,每次解构都会创建新数组,频繁操作大数组时,[...rest] 的内存开销比直接用索引访问高;若只是读取后续元素,考虑用 for 循环或 arr.slice(n) 更直接。
真正容易被忽略的是:解构赋值本身不改变原数组,但 ... 收集过程会触发迭代器遍历——如果右侧是自定义迭代器且有副作用(比如生成器函数),那每次解构都可能执行一次完整迭代。

















