简单了解一下JavaScript的argument
函数调用的时候,浏览器每次都会传递进两个隐式参数:一个是函数的上下文对象this
,另一个则是封装实参的类数组对象arguments
。
arguments被定义为
对象,但对象的属性是无序的,而arguments
是用来存储实参的,是有顺序的,它具备和数组相同的访问性质及方式,并拥有数组长度属性length
,所以arguments
是特殊的对象,又叫类数组对象。可以arguments[i]来访问对象中的元素,但它不能用数组的一些方法,例如push,pop,slice等。
1、Arguments的length属性
function argTest(a,b,c){ var d = arguments.length; //实际传参个数 var e = argTest.length; //期望传参个数 console.log(d); console.log(e); } argTest(1,2); //t=2,e=3 argTest(1,2,3); //t=3,e=3 argTest(1,2,3,4); //t=4,e=3
结论:ECMAScript
不会验证传递给函数的参数个数是否等于函数定义的参数个数。
2、Arguments的参数访问
arguments
访问单个参数的方式与访问数组元素的方式相同,可以用arguments[i]来访问函数所传的参数。通过length
属性可以知道实参的个数。
function fn() { console.log(arguments[0]); // name console.log(arguments[1]); // age console.log(arguments.length); // 2 } fn('name', 'age');
3、Arguments的callee调用
Arguments的callee属性用来调用函数本身,当函数正在执行时才可调用,可以用来实现方法的递归调用。
function argTest(a,b,c){ var e = arguments.callee.toString(); console.log(e); } argTest(); //打印出函数本身
function fn() {
console.log(arguments.callee === f3); // true
}
fn('name', 'age')
4、Function对象caller属性
Function对象的caller属性可以指向当前函数的调用者,当调用者函数正在执行时才可调用
function callerTest(){ if(callerTest.caller){ var caller = callerTest.caller.toString(); console.log(caller); }else{ console.log("no caller") } } function handler(){ callerTest(); } function handlerToHandler(){ handler(); } callerTest(); //no caller handler(); //返回调用者handler函数 handlerToHandler(); //返回调用者handler函数 / * no caller function handler(){ callerTest(); } function handler(){ callerTest(); } */
5、arguments的修改
arguments
对象是允许在函数运行时进行修改的
function fn() { arguments[0] = 'sex'; console.log(arguments[0]); // sex } fn('name', 'age');
6、arguments转化成真实数组
arguments
是类数组对象,除了length
属性和索引元素之外没有任何Array
属性。例如,它没有 pop
方法。但是它可以被转换为一个真正的Array
:
function fn(){ // 可以使用slice来将arguments转换为真实数组 var args1 = Array.prototype.slice.call(arguments); var args2 = [].slice.call(arguments); // 也可以使用Array.from()方法或者扩展运算符来将arguments转换为真实数组 var args3 = Array.from(arguments); var args4 = [...arguments]; } fn('name', 'age');
7、Arguments的应用
a:验证实参和形参个数是否相等
function fn (a, b, c) { if (fn.length != arguments.length) { console.log('形参和实参的个数不一致'); } else{ console.log('形参和实参的个数一致'); } } fn(1, 2);
b:callee
来让匿名函数实现递归(注意是匿名函数)
function sum(n) { if (n == 1) { return 1; } else { return n + arguments.callee(n - 1); // 5 4 3 2 1 } } console.log(sum(6)); // 21
function factorial(n){
if(n == 1){
return 1;
}else{
n * arguments.callee(n-1);
}
}
factorial(5); // 120
c: 遍历参数求和或者求最大值
function max () { var max = arguments[0]; for (item of arguments) { if (item > max) { max = item; } } return max; } console.log(max(6, 3, 5, 9, 2)); // 9
d:方法模拟重栽
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。 Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。
// 未重载 function add(num1, num2) { console.log(1); } function add(num1, num2, num3) { console.log(2); } add(1, 2); //2 add(1, 2, 3);//2 // 重载 function add(num1, num2, num3) { if (arguments.length === 2) { console.log("Result is " + (num1 + num2)); } else if (arguments.length === 3) { console.log("Result is " + (num1 + num2 + num3)); } } add(1, 2); // 3 add(1, 2, 3) // 6