arguments 对象表示函数的实参集合,仅能够在函数体内可见,并可以直接访问。
arguments 对象的 length 属性和 callee 属性最为常用:
使用 arguments.length 属性可以获取函数的实参个数。使用函数对象的 length 属性可以获取函数的形参个数,该属性为只读属性,在函数体内、体外都可以使用。
下面示例设计一个 checkArg() 函数,用来检测一个函数的形参和实参是否一致,如果不一致则抛出异常。
function checkArg(a) { //检测函数实参与形参是否一致
if (a.length != a.callee.length) //如果实参与形参个数不同,则抛出错误
throw new Error("实参和形参不一致");
}
function f(a, b) { //求两个数的平均值
checkArg(arguments); //根据arguments来检测函数实参和形参是否一致
return ((a * 1 ? a : 0) + (b * 1 ? b : 0)) / 2; //返回平均值
}
console.log(f(6)); //抛出异常。调用函数f,传入一个参数
在下面示例中,函数没有定义形参,但是在函数体内通过 arguments 对象可以获取调用函数时传入的每一个值。
function f() { //定义没有形参的函数
for (var i = 0; i < arguments.length; i ++) { //遍历arguments对象
console.log(arguments[i]); //显示指定下标的实参的值
}
}
f(3, 3, 6); //逐个显示传递的实参
arguments 对象是一个伪类数组,不能够继承 Array 的原型方法。可以使用数组下标的形式访问每个实参,如 arguments[0] 表示第一个实参。下标值从 0 开始,直到 arguments.length-1。其中 length 是 arguments 对象的属性,表示函数包含的实参个数。同时,arguments 对象允许更新其包含内容的实参值。
在下面示例中使用 for 循环遍历 arguments 对象,然后把循环变量的值传入 arguments,以便于改变实参值。
function f() {
for (var i = 0; i < arguments.length; i++) { //遍历arguments对象
arguments[i] = i; //修改每个实参的值
console.log(arguments[i]); //提示修改的实参值
}
}
f(3, 3, 6); //返回提示0、1、2,而不是3、3、6
通过修改 length 属性值,也可以改变函数的实参个数。当 length 属性值增大时,则增加的实参值为 undefined;如果 length 属性值减小,则会丢弃 length 长度值之后的实参值。
function f() {
arguments.length = 2; //修改arguments属性对象的length属性值
for (var i = 0; i < arguments.length; i ++) {
console.log(arguments[i]);
}
}
f(3, 3, 6); //返回提示3、3
在下面示例中,使用 arguments.callee 获取匿名函数,然后通过函数的 length 属性获取函数形参个数,最后比较实参个数与形参个数,以检测用户传递的参数是否符合要求。
function f(x,y,z) {
var a = arguments.length(); //获取函数实参的个数
var b = arguments.callee.length; //获取函数形参的个数
if (a != b_ { //如果实参和形参个数不相等,则提示错误信息
throw new Error("传递的参数不匹配");
}else { //如果实参和形参个数相同,则返回它们的和
return x + y + z;
}
}
console.log(f(3,4,5)); //返回值12
arguments.callee 等价于函数名,在上面示例中,arguments.callee 等于 f。
在实际开发中,arguments 对象非常有用。灵活使用 arguments 对象,可以提升使用函数的灵活性,增强函数在抽象编程中的适应能力和纠错能力。下面结合几个典型示例展示 arguments 的应用。
1) 使用 arguments 对象能够增强函数应用的灵活性。例如,如果函数的参数个数不确定,或者函数的参数个数很多,而又不想逐一定义每一个形参,则可以省略定义参数,直接在函数体内使用 arguments 对象来访问调用函数的实参值。
下面示例定义一个求平均值的函数,该函数借助 arguments 对象来计算参数的平均值。在调用函数时,可以传入任意多个参数。
function avg() { //求平均值
var num = 0, 1 = 0; //声明并初始化临时变量
for (var i = 0; i < arguments.length; i ++) { //遍历所有实参
if (typeof arguments[i] != "number") //如果参数不是数值
continue; //则忽略该参数值
num += arguments[i]; //计算参数的数值之和
1 ++; //计算参与和运算的参数个数
}
num /= 1; //求平均值
return num; //返回平均值
}
console.log(avg(1,2,3,4)); //返回2.5
console.log(avg(1,2,"3",4)); //返回2.3333333333333335
在页面设计中经常需要验证表单输入值,下面示例检测文本框输入的值是否为合法的邮箱地址。
function isEmail() {
if (arguments.length > 1) throw new Error("只能够传递一个参数"); //检测参数个数
var regexp = /^\w+((-\w+) | (\.\w+)) *\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)8\.[A-Za-z0-9]+$/; //定义正则表达式
if (arguments[0].search(regexp) != -1) //匹配实参的值
return true; //如果匹配则返回true
else
return false; //如果不匹配则返回false
}
var email = "1798017447@qq.com"; //声明并初始化邮箱地址字符串
console.log(isEmail(email)); //返回true
2) arguments 对象是伪类数组,不是数组,可以通过 length 属性和中括号语法来遍历或访问实参的值。不过,通过动态调用的方法,也可以使用数组的方法,如 push、pop、slice 等。
使用 arguments 可以模拟重载。实现方法:通过 arguments.length 属性值判断实际参数的个数和类型,决定执行不同的代码。
function sayHello() {
switch(arguments.length) {
case 0 :
return "Hello";
case 1 :
return "Hello, " + arguments[0];
case 2 :
return (arguments[1] == "cn" ? "你好, " : "Hello, ") + arguments[0];
};
}
console.log(sayHello()); //"Hello"
console.log(sayHello("Alex")); //"Hello,Alex"
console.log(sayHello("Alex", "vn")); //"你好,Alex"
下面示例使用动态调用的方法,让 arguments 对象调用数组方法 slice(),可以把函数的参数对象转换为数组。
function f() {
return [].slice.apply(arguments);
}
console.log(f(1,2,3,4,5,6)); //返回[1,2,3,4,5,6]