介绍
arguments是一个对应于传递给函数的参数的类数组对象, 它只定义在函数体内
在使用的时候要注意以下几点
arguments对象是所有 (非箭头) 函数中都可用的局部变量.
对于箭头函数,并不是没有
arguments,而是没有 自己 的arguments
举个例子:
function foo() {
setTimeout(() => {
console.log(arguments)
}, 1000)
}
foo(1, 2, 3)
// 输出 [Arguments] { '0': 1, '1': 2, '2': 3 }
arguments对象不是一个Array,它类似于Array它拥有索引元素和length属性,可以被转换成一个真正的Array
var args = Array.prototype.slice.call(arguments)
var args = [].slice.call(arguments)
const args = Array.from(arguments)
const args = [...arguments]
arguments 在函数中主要有两个用途
- 用来判断有多少个参数传入函数, 还可以用来指代未命名的参数
- 除了数组元素和
length属性, 还可以通过callee属性解除函数体内的代码与函数名的耦合状态
arguments.callee
指向参数所属的当前执行的函数
举个例子:
function factorial(num) {
if (num <= 1)
return 1
else
return num * factorial(num - 1)
}
上述代码定义了一个阶乘函数,使用到了递归算法,但是函数名 factorial 与 函数执行紧紧耦合在一起,为了消除这种现象可以使用 arguments.callee
function factorial(num) {
if (num <= 1)
return 1
else
return num * arguments.callee(num - 1)
}
这样一来,不管函数调用叫什么名字,都可以完成递归调用.
但是现在已经不推荐使用 arguments.callee
原因:访问
arguments是个很昂贵的操作,因为它是个很大的对象,每次递归调用时都需要重新创建。影响现代浏览器的性能,还会影响闭包。
所以需要再次改造 (利用立即执行函数来实现):
function factorial(num) {
if (num <= 1)
return 1
let flag = 1
return (function fn() {
flag *= num
num--
if (num != 0)
fn()
return flag
})()
}
arguments.length
传递给函数的参数数量
该属性表示的是实际传入的参数个数而不是声明的参数个数
实参长度:
arguments.length形参长度:
arguments.callee.length
借此可以用来检查传入参数个数的正确性:
function check(args) {
const actual = args.length // 实际的参数个数
const expected = args.callee.length // 期待的参数个数
if (actual != expected)
throw new Error(`参数个数有误,期望值:${expected};实际值:${actual}`)
}
function fn(x, y, z) {
check(arguments) // 检查参数个数的正确性
return x + y + z
}