调用对象定义了一个特殊的属性,名称arguments,它实际上引用了一个特殊对象arguments对象,因为arguments属性是调用对象的一个属性,因此它的状态和局部变量以及形参是相同的。arguments.length可以获取传递给参数的实参数量
废话不多少,例子说明一切
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
</head>
<body>
<script language="javascript">
<!--
function f(x,y,z)
{
if (f.length !=arguments.length)
{
//可以通过读取函数的length和arguments的length属性值来检查形式参数的数量是否相等
//因为前者恰好是形参的数量,而后者是实参数量
//如果不相等抛出异常
throw new error('function f called with' +arguments.length+'arguments,but it expects'+f.length+'arguments');
}
else
{
document.write("f("+[x,y,z]+')'+'<br/>');
}
}
try
{
f(1,2,3);
f(2,4);//抛出异常,后面的将不再执行
f(4);
f("a","b","c","d","e","f");
}
catch (ex)
{
document.write(ex.message);
}
//-->
</script>
</body>
</html>
运行结果:
java代码
f(1,2,3)
function f called with2arguments,but it expects3arguments
arguments的行为有点想数组,但它其实并不是数组,它不具备javascript核心数组的一些方法如join、sort、slice等
一个使用arguments对象那个接收任意参数的例子
java代码
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
</head>
<body>
<script language="javascript">
<!--
function f()
{// 利用arguments来读取任意个数的参数
document.write("f(" +array.apply(null,arguments) + ")" +"<br/>");//apply()应用某一对象的一个方法,用另一个对象替换当前对象。
}
f(1,2,3);
f("a","b");
f(true);
//-->
</script>
</body>
</html>
一个使用arguments对象模拟函数重载的例子
java代码
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title> new document </title>
</head>
<body>
<script language="javascript">
<!--
function point()
{
if(arguments.length ==0)//如果没有参数
{
//默认的xy属性都设置0
this.x=0;
this.y=0;
this.tostring=function()
{
return this.x+" "+ this.y ;
}
}
else if (arguments.length <2)//如果实参小于2
{
var p=arguments[0];
if (p instanceof point )//判断实参类型如果是point,那么执行属性复制
{
this.x =p.x;
this.y =p.y
this.tostring=function()
{
return this.x+" "+ this.y ;
}
}
else if ( typeof p=="number" || p instanceof number)//如果是数值,那么这个值作为当前point的x属性值,y属性默认0
{
this.x=(number)(p);
this.y=0;
this.tostring=function()
{
return this.x+" "+ this.y ;
}
}
else
{//如果这个参数既不是point又不是number,抛出类型异常
throw new typeerror("参数类型错误!")
}
}
else if (arguments.length==2)
{
var x= arguments[0];
var y= arguments[1];
//否则当参数数量为两个并且为number类型的时候,把她们分别作为point的xy
if ((typeof x=='number' || x instanceof 'number') && typeof y == 'number' ||y instanceof 'number')
{
this.x = x;
this.y = y;
this.tostring=function()
{
return this.x+" "+ this.y ;
}
}
else
throw new typeerror('参数类型错误!');
}
else
{
throw new typeerror("参数类型错误!");
}
}
function dwn(s)
{
document.write(s+"<br/>");
}
dwn(new point());//00
dwn(new point(new point()));//00
dwn(new point(3));//30
dwn (new point(4,5));//45
//-->
</script>
</body>
</html>
需要注意的是:在使用了命名参数的函数中,arguments中的参数也始终是相应命名参数的别名,不管这个参数是值类型还是引用类型,改变arguments中的参与一定会影响到对应的命名参数,反之亦然如:
java代码
function f(x)
{
alert(x);//参数初始值
arguments[0]++;//改变参数的值
alert(x);//x的值发生了改变
}
arguments对象还提供了一个有用的属性叫做callee,它被用来应用当前正在执行的函数,它提供了一种匿名的递归调用能力,这对于闭包说非常有用,如:
用闭包计算10的阶乘
java代码
function(x){
return x>1?x*arguments.callee(x-1):1
}(10);