arguments 是函数内自动可用的类数组对象,保存所有传入参数;因非真数组且不兼容箭头函数等,现代 JS 推荐用剩余参数替代。

arguments 是什么,为什么现在不推荐直接用它
arguments 是一个类数组对象,函数内部自动可用,保存了调用时传入的所有参数。但它不是真正的 Array,没有 map、filter 等方法,也不能用展开语法直接解构——这正是最容易踩坑的地方。
现代 JS 推荐用剩余参数(...args)替代 arguments,因为它是真数组、类型安全、支持箭头函数,且在严格模式下不会干扰引擎优化。但如果你维护老代码、或需要兼容某些不能改签名的场景(比如封装已有函数),还是得懂怎么安全用 arguments。
如何把 arguments 转成真数组再操作
不能直接写 arguments.map(...),会报 TypeError: arguments.map is not a function。必须先“转换”:
- 最稳妥:
Array.prototype.slice.call(arguments)(兼容所有环境,包括 IE8) - ES6+ 推荐:
Array.from(arguments)(语义清晰,可传映射函数) - 注意别用
[...arguments]:虽然看起来简洁,但在非严格模式的普通函数里可能出错;箭头函数根本没arguments,写了就ReferenceError
示例:一个兼容旧版的求和函数
function sum() {
const args = Array.from(arguments);
return args.reduce((a, b) => a + b, 0);
}arguments.callee 和严格模式的冲突
以前有人用 arguments.callee 实现匿名递归,比如阶乘函数内调自己。但严格模式下它被禁用,直接访问会抛 TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions。
解决办法只有两个:
- 去掉
'use strict'(不推荐,牺牲安全性和性能) - 改用具名函数表达式:
const factorial = function fn(n) { return n ,这样递归调用的是 <code>fn,不依赖arguments
arguments 的 length 和实参个数不一致的情况
arguments.length 只反映调用时传了几个值,不管函数定义几个形参。但如果函数用了默认参数、解构或 rest 参数,arguments 就更不可靠了:
- 有默认参数时,
arguments仍包含所有传入值,但对应形参可能已被覆盖(例如function f(a = 10) { console.log(arguments[0]); },调用f()时arguments[0]是undefined,而a是10) - 用了
...rest后,arguments还是全量,但 rest 参数本身已是数组,无需再转 -
arguments不响应形参重赋值(a = 20不影响arguments[0]),这点和早期 JS 规范有关,现在已统一为“不绑定”
真正需要原始调用痕迹的场景极少,多数时候你该用 ...args 或明确的参数设计。
如果必须用 arguments,记住它只是一份快照,不活、不灵、不现代——别把它当第一选择。

















