ECMAScript函数是任性的
他可以任意传进N个参数,而且不限男女,哦不对——不限类型。其实是因为ECMAScript中的参数在内部是用一个数组来表示的,在函数体内,存在一个arguments对象,可以通过该对象去访问参数数组。
function love (who1, who2) {
alert(who1 + " love " + who2);
}
var who1 = "I" ;
var who2 = "you" ;
love(who1, who2);
在上面的代码中定义了一个love函数,并定义了两个参数,命名为who1和who2,我们称之为命名参数(形参)。但对参数进行命名是无所谓的,不是必需的,仅仅是为了提供便利。对于其他大多数语言来说,事先要创建好一个函数签名(确定形参的类型和数量),在之后的调用就得和该签名一致。而ECMAScript独立门派,就算命名好了形参,之后调用传实参时也可视心情而定,想传多少实参就传多少,解析器不会验证其命名参数。
arguments对象中有一个length属性,正式用来保存参数的个数的,love函数中 arguments.length = 2 。值得注意的是,length的值并不是由命名参数个数决定的,而是你调用的时候实际传了多少个参数(实参)进去,就是多少个,说白了最开始创建的函数签名就只是做做样子罢了,然并卵!
function love (who1, who2) {
alert(arguments [0 ] + " love " + who2 + " " + how);
alert(arguments .length);
}
var who1 = "I" ;
var who2 = "you" ;
var how = "so much!" ;
love(who1, who2, how);
love函数中定义的形参只有2个(who1和who2),但是为了表达我对你浓浓的爱意,我在调用我的love的时候多传了一个how,所以 arguments.length = 3 。另外你可能也发现了,alert中我把who1改成了arguments[0],其实都是一样的,就是前面所说的arguments就像数组一样存放着传进来的参数,这里传进来3个参数,即arguments[0] = who1,arguments[1] = who2,arguments[2] = how,这也说明arguments对象可以与命名参数一起使用。
但是如果我只定义了N个形参,但是只传入了不到N个实参,那么没有被传值的参数则自动被赋予undefined值。
function love (who1, who2) {
alert(who1 + " love " + who2);
}
var who1 = "I" ;
love(who1);
上面的love函数有两个形参who1和who2,调用时只传了一个who1,所以who2(其实是arguments[1],who2根本就不存在,跟之后的什么who3、who4、who5…一样不存在,有的只是arguments[3]、arguments[4]、arguments[5]…,且都是undefined值)的值就为undefined。
比较有意思的是arguments的值始终与命名参数的值保持同步
function love (who1, who2) {
arguments [1 ] = "her" ;
alert(who1 + " love " + who2);
}
var who1 = "I" ;
var who2 = "you" ;
love(who1, who2);
由于who2心里的人arguments[1]变了,那who2本人也就变了心。哎!再也不相信爱情了!
这样看来,感觉arguments和命名参数好像是指向了相同的内存空间,其实不然,只是arguments的值会自动反映到对应的命名参数,但他们的内存空间是独立的!
顺便说一下,由于ECMAScript函数没有签名,其参数只是由包含0个或多个值的数组来表示的,所以ECMAScript函数不能真正实现重载。