在调用函数时,浏览器每次都会传递进两个隐含的参数
- 函数上下文对象this
- 封装实参对象 arguments
arguments是类数组对象,它可以通过索引来操作数据,也可获取长度,在调用函数时,我们所传递的实参都会在arguments中保存。
既然是对象那其对应也有属性,这里先探讨两个callee,length
length属性
arguments.lenght可以用来获取实参的长度,我们即使不定义形参,也可以通过arguments来使用实参。
arguments[0]表示第一个实参
arguments[1]表示第二个实参
......
//先定义一个函数
function fun(){
console.log(arguments);
console.log(arguments instanceof Array);
console.log(arguments.length);
console.log(arguments[1]);
console.log(Array.isArray(arguments));
}
fun("hello","thank");
输出结果:
callee属性
这个属性对应一个函数对象,就是当前正在指向的函数对象。
function fun(){
console.log(arguments.callee==fun);
}
fun("hello","thank");//返回true
当然看到这里还是不太清楚这个到底有啥用,这里再介绍几种情景:
- 可以模拟函数重载
首先我们知道js语法不支持重载,如下:
function fun(a,b){
return a+b;
}
console.log(fun(1,2));
//再来个同名函数
function fun(a,b,c){
return a+b+c;
}
console.log(fun(1,2,3));
最后返回值示NaN和6,这就说明后面的函数把前一个同名函数覆盖掉了,从而可以得出js函数不存在重载。
但是使用arguments即可以模拟实现函数的重载,如下:
function fun(){
//如果用户传入一个参数,求平方
if(arguments.length==1){
console.log(arguments[0]*arguments[0]);
}
//如果用户传入两个参数,就求和
if(arguments.length==2){
//如果用户传入两个参数,就求和
console.log(arguments[0]+arguments[1]);
}
}
fun(4); //16
fun(4,5); //9
function add(){
//遍历arguments中每个元素,并累加
for(var i=0,sum=0;i<arguments.length;i++)
sum+=arguments[i];
return sum;//返回和
}
console.log(add(1,2,3)); //6
console.log(add(1,2,3,4,5,6)); //21
这就是JS利用arguments模拟重载的效果。
还有,在js中不需要明确指出参数名,就能访问它们,例如:
function test(){
var s="";
for(var i=0;i<arguments.length;i++)
{
s+=arguments[i]+",";
}
return s;
}
console.log(test("name","age"));
实现匿名的递归函数
var sum = function (n) { if (1 == n) { return 1; } else { return n + arguments.callee(n - 1); //6 5 4 3 2 1 } } alert(sum(6));//21
延伸知识
var length = 10; function fn() { console.log(this.length); } var obj = { method: function(fu) { fn(); arguments[0](); } }; obj.method(fn,1);//输出10,2
注意函数fn的指向
第一个值为10,执行的是method里面的第一行"fn()",这里this指向的window。所以输出的值为全局变量的length。
第二个值为2,虽然arguments[0]()==fun(),但是这里的this指向的是arguments这个对象,所以输出值为arguments的长度。
另外:arguments对象和Function是分不开的。因为arguments这个对象不能显式创建,arguments对象只有是函数时才可用。