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) {
var actual = args.length; // 实际的参数个数
var expected = args.callee.length; // 期待的参数个数
if( actual != expected ) {
throw new Error("参数个数有误,期望值:" + expected + ";实际值:" + actual);
}
}
function fn(x,y,z) {
check(arguments); // 检查参数个数的正确性
return x+y+z;
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END