JavaScript 的 rest 参数是捕获函数多余实参的语法糖,必须位于形参末尾且唯一,生成真数组;与 arguments 不同,它原生支持数组方法、适用于箭头函数,且仅在函数参数、数组/对象解构中合法。

JavaScript 的 rest 参数不是“剩余参数”的翻译腔,而是实打实的语法糖,用来捕获函数中未命名的多余实参,本质是把它们自动聚合成一个真数组。
rest 参数必须写在形参列表末尾,且只能有一个
它用 ...args 的形式出现,位置和数量都有硬性限制:
- 必须放在所有具名形参之后,否则报错:
Unexpected token ... - 一个函数里最多只能有一个 rest 参数,写两个会直接 SyntaxError
- 它不是 arguments 对象——
args是真正的Array实例,可直接调用.map()、.filter()等方法
和 arguments 对象的关键区别在哪
很多人以为 rest 参数只是 arguments 的替代品,其实它们定位不同:
-
arguments是类数组对象,没有forEach、includes等方法,还得靠Array.from(arguments)或[...arguments]转换 -
...args从一开始就是数组,类型安全,IDE 能推导类型(尤其配合 TypeScript) -
arguments在箭头函数里不可用;rest 参数天然支持箭头函数
const sum = (...numbers) => numbers.reduce((a, b) => a + b, 0); sum(1, 2, 3); // 6 —— 没有 arguments,也不需要转换
常见误用:试图在解构或对象字面量里“单独”用 rest
rest 参数只合法出现在函数形参、数组解构、对象解构这三处。下面这些写法全错:
立即学习“Java免费学习笔记(深入)”;
-
function foo(...a, b) {}—— rest 必须在最后 -
const obj = { ...x, y: 1 };—— 这是展开运算符(spread),不是 rest 参数,虽然语法一样但语义不同 -
if (true) { ...items }—— rest 不能独立成句,必须依附于声明或接收上下文
记住:... 是同一个符号,但在函数参数位置叫 rest,在实参/字面量位置叫 spread —— 判断依据永远是它出现的位置和作用对象。
实际用法:封装可变参数工具函数最自然
比如写一个兼容老浏览器的日志函数,需要保留所有传入内容并加前缀:
const log = (prefix, ...msgs) => {
console.log(`[${prefix}]`, ...msgs);
};
log('API', 'fetch success', 200, { id: 123 });
这里 ...msgs 收集了除第一个外的所有参数,后面再用 ...msgs 展开传给 console.log —— 同一个符号,在形参是 rest,在实参是 spread,一气呵成。
真正容易被忽略的是:rest 参数不会捕获默认值未触发的形参,也不会跳过 undefined;它只管“多出来的”那部分。传 foo(1, undefined, 2),如果函数定义是 foo(a, b = 42, ...rest),那么 rest 是 [2],b 是 undefined(因为没跳过,只是没赋默认值)。这点和很多人的直觉相反。











