在实际项目开发中,目前还是很少使用到JavaScript 中的arguments对象,那么它到底是干什么用的呢
arguments是JavaScript中的一个类数组对象,它代表传给一个正在执行的函数function的参数列表。
看完这个定义,需要明白,它是一个对象,不是一个数组,但是它这个对象却又类似数组,也就是说样子和数组类似. 那它的内容,它里面的内容是传递给正在执行的函数Function的参数列表
上面都特别强调,是 正在执行的函数function,这也就是说,arguments对象只有函数已经开始执行时,才可以使用,才能取到值。 所以, arguments对象存储的是实际传递给函数的参数,而不是函数声明时所定义的参数列表
我们来看一个例子,能够更直观的理解它
function showArgs(){ console.log(arguments);}showArgs("a","1",{ test: "only for test" });执行结果如下["a","1",Object]
上面的函数showArgs作用是输出它的参数列表,当我们调用它 showArgs("a","1",{ test: "only for test" }) 时,可以看到,它总共包括3个参数,分别是”a“,"1",{ test: "only for test" }, 其中,第三个{ test: "only for test" }是个object, javascript无法直接输出它,所以就输出了object
如果要访问其中某一个参数呢,arguments提供和数组一样的方式来访问单个参数,也就是使用下标arguments[0],arguments[1]来访问.
形式应该是这样的 [function].arguments[n] function在这里可以省略,表示的是当前正在执行的Function对象的名字
在上面的函数中, arguments[0] = "a", arguments[1] = "1" , arguments[2] = {test: "only for test"}
接下来,我们来看看arguments对象的一些属性
1. length属性
上面说了arguments是个类数组对象,它和数组一样,也有一个length属性,我们可以通过arguments.length来获得传入函数的参数个数
2. callee属性
arguments.callee的值,是当前正在被执行的函数,也就是说是当前这个arguments它所在的函数. 我们上面论述了,arguments在函数被调用时才会有效,它才存在。 因此,在函数没有被调用时 arguments.callee是不存在的.
另外 特别注意 在JavaScript的严格模式下面, arguments.callee是不可以使用的
3. arguments转成真正的数组
我们上面说了,arguments是一个类数组的对象,但不是数组,它虽然也有和数组一样的length属性,也可以像数组一样采用arguments[n]下标形式进行访问。 但它并不是数组,那么我们可以把它转换为数组吗 ? 答案是可以的
采用如下方法 Array.prototype.slice.call(arguments); 还可以用一个简易的写法 [].slice.call(arguments);
事实上, slice方法可以用来把满足一定条件的对象转换成数组, 这个在这里我们就不详细论述了
我们来看一个例子
function TestArguments(){ var testArray = Array.prototype.slice.call(arguments); //把arguments转换成了真正的数组 // var testArray = [].slice.call(arguments); //也可以这样简写,也是把arguments转换成数组 var sum = 0; testArray.forEach( //可以调用数组的forEach方法 function(value) { sum += value; }); return sum;}
当然,也可以调用JavaScript中的Array.from()方法来把arguments转换为真正的数组
JS中的Array.from()方法就是用来从一个类似数组或者可迭代对象中创建一个新的数组实例. 我们还是来看一个例子
function testfunc(){ return Array.from(arguments);}testfunc(7,8,9); //输出 [7,8,9]
4. 用arguments来模拟重载
我们知道C# 语言中有重载,但是JavaScript中没有重载. 我们举一个例子来说明JavaScript中没有重载
function add(arg1,arg2) //第1个add方法{ console.log("第一个add方法"); return arg1 + arg2;}function add(arg1,arg2,arg3) //第2个add方法{ console.log("第2个add方法"); return arg1 + arg2 + arg3; }add(1,2); //输出 第2个add方法add(1,2,3); //输出 第2个add方法
在上面的例子中,我们可以看到,函数调用的始终都是第2个add方法, 因为JavaScript是按照顺序来执行的. 而不是像C#中那样,存在函数重载,会根据参数的不同调用不同的重载函数
但是我们如果想实现这样的重载效果,有没有方法来实现呢。 思考一下,它本质上就是根据参数个数不同输出不一样的结果,而实际传入的参数个数是可以通过arguments来判断的。
我们来写一个例子
function add(arg1,arg2,arg3){ if(arguments.length === 2) { console.log(arg1 + arg2); } else if (arguments.length === 3) { console.log(arg1 + arg2 + arg3); } }add(5,5); //输出 10add(5,5,5); // 输出 15
5. arguments与默认参数
我们知道C#中有默认参数,我们来看看C#中默认参数的例子
public string add(int a, int b = 10, int c = 15){ return a + b + c;}
在这个例子中,传入的参数b的默认值为10, c的默认值为15. 也就是说我们在调用add函数时,如果没有给b和c传值的话,就会使用它们的默认值10和15
那么,在JavaScript中,有没有同样的参数默认值设定呢,答案是有的,我们来看一个例子
function testfunc(firstArg = 0, secondArg =1){ console.log(firstArg,secondArg); }testfunc(100); //输出 100 1
看上面这个JavaScript函数,有两个参数firstArg,secondArg. 两个参数都有默认值,当调用该函数testfunc(100) 时,传入了一个参数100,自然就是覆盖了第一个参数,第2个参数没有传入,自然会取它的默认值1,所以输出100,1
那这个又跟我们这篇博客中的arguments有什么关系的,我们来把它修改一下看看
function testfunc(firstArg = 0, secondArg =1){ console.log(arguments[0],arguments[1]); console.log(firstArg,secondArg); }testfunc(100); //输出100 undefined100 1
上面可以看到,当调用函数testfunc(100) 时, console.log(arguments[0],arguments[1]) 输出的是 100 undefined, 也就是说arguments[1]还是没有值,它没有取默认传入的参数secondArg=1
这样符合arguments的定义,arguments指的是调用函数时,实际传入的参数,在上面例子中,调用函数testfunc(100), 实际传入的参数就是只有一个100. 由此可见,默认参数对arguments完全没有影响