展开运算符(...)用于拆解数组/对象,剩余参数(...)用于收拢多余参数;前者在函数调用、数组/对象字面量中使用,后者仅限函数最后形参或解构赋值右侧,二者位置和上下文决定语义。

JavaScript 的展开(spread)和剩余(rest)参数看起来符号相同(都是 ...),但作用完全相反:展开是“把一个数组或对象拆开”,剩余是“把多个参数收拢成一个数组”。用错场景会直接报错或逻辑异常。
展开运算符 ... 用于解构和合并
展开运算符必须出现在“被操作值”的位置,比如函数调用、数组字面量、对象字面量中。它不能单独存在,也不能放在赋值左侧(除非配合解构)。
- 函数调用时展开数组:
Math.max(...[1, 3, 2])等价于Math.max(1, 3, 2) - 合并数组:
[...arr1, ...arr2]创建新数组,不修改原数组 - 浅拷贝对象:
{...obj}只复制第一层属性,嵌套对象仍共享引用 - 错误用法:
...arr单独写一行会报SyntaxError: expected expression
剩余参数 ... 必须是函数最后一个形参
剩余参数收集“未被单独声明的实参”,本质是自动创建一个真正的 Array 实例,不是类数组对象(如 arguments)。
- 正确写法:
function fn(a, b, ...rest) { }——rest是数组,包含从第 3 个起的所有参数 - 不能有后续参数:
function fn(...rest, last) { }会语法错误 - 与解构共用时注意顺序:
const [first, ...others] = arr合法;const [...others, last] = arr不合法 - 性能提示:大量参数传入时,
rest数组创建有轻微开销,但通常可忽略
常见混淆点:展开 vs 剩余,看位置和上下文
同一个 ... 符号,在函数定义里是剩余参数,在函数调用里就是展开运算符。关键看它“在哪儿”以及“作用于谁”。
立即学习“Java免费学习笔记(深入)”;
- 定义函数时出现:
function f(...args)→ 剩余参数 - 调用函数时出现:
f(...arr)→ 展开运算符 - 对象中出现:
{...obj, c: 3}→ 展开(复制属性) - 解构赋值中出现:
const {a, ...rest} = obj→ 剩余(提取剩余属性为新对象) - 类型检查陷阱:TypeScript 中
...args: string[]是剩余,但fn(...args)的args类型必须是数组或元组,否则类型不匹配
最易被忽略的是:剩余参数不捕获已命名参数,展开运算符不支持 Map/Set 直接展开(需先转为数组),还有在旧环境(如 IE)中两者均不支持——如果要兼容,得用 Babel 转译或手动降级处理。











