Fork me on GitHub

 函数声明语句:function f(x){},其中x就是参数。

参数分为两种:

  • 形参(parameter):函数定义时圆括号里的数据。
  • 实参(arguments);函数调用时,传给函数作为参数的数据。

EMCAScript规定在调用函数时,可传入任意数量,任意类型的参数,可以不跟函数定义时传入的形参数量相对应。为什么会这样呢?

原因就是,EMACAScript中的参数在内部是用一个数组来表示的,函数接收的始终是这个数组,而不关心包含哪些参数。而且,在函数体内也可以通过arguments这个对象来访问这个参数数组,从而获取传递给函数的每一个参数。(arguments就是一个对象--函数的一个内部对象,和this一样。)因此arguments看起来就像一个类数组了。可以用arguments[n]来访问各个位置的元素了.

 

要了解arguments对象,就需要先函数的内部属性。

函数内部,有两个特殊对象:arguments 和 this。

arguments是一个类数组对象,包含着传入函数中的所有参数。该对象有一个属性callee,该属性是一个指针,指向拥有这个arguments对象的函数。经典例子是阶乘函数:

 1 function factorial(num){
 2     if(num <= 1){
 3         return 1;
 4     }else{
 5         return num * factorial(num-1);
 6     }
 7 }
 8 
 9 //修改一下,消除函数的执行与函数名紧密的耦合在一起,
10 function factorial(num){
11     if(num <= 1){
12         return 1;
13     }else {
14         return num * arguments.callee(num-1);
15     }
16 }
17 
18 //修改后函数名factorial就没出现在函数体内部,因此,无论引用函数时使用什么名字,都能保证正常完成递归。
19 //例如
20 var trueFactorial = factorial;
21 factorial = function(){
22     return 0;
23 };
24 alert(trueFactorial(5));  //120
25 alert(factorial(5));   //0
26 //在上面的例子里,变量trueFactorial 获得了factorial的值,实际上就是在另一个位置上保存了一个指向函数的指针,就是让另一个变量也可以应用该函数,正如在函数定义时说的,函数名是一个指向函数的指针,函数体本身存在那里,通过函数名可以访问罢了,二者相互独立,又存在某种联系。
27 //然后将一个返回0的新函数赋给变量factorial。如果在函数体内有变量名factorial,如第一个例子,则trueFactorial()就会返回0.但改成arguments.callee后就能够让trueFactorial正常计算。

与callee属性对应的就是caller属性,arguments对象也拥有caller属性,即:arguments.caller。但在严格模式下访问它会报错,而在非严格模式下这个属性始终是undefined。该属性主要就是为了分清arguments.caller和函数的caller属性。函数的caller属性指向调用该函数的外部函数。

arguments.callee.caller 和函数的caller属性等效。

function outer(){
    inner();
}
function inner(){
    alert(inner.caller);  //等价于alert(arguments.callee.caller);
}
outer();   //返回outer函数的代码

 

arguments还有一个length属性,返回传入参数的个数。和Array.length类似。

 

前面说的在函数内部可以通过arguments对象访问传入的参数。那也可以和命名参数一起在函数内部使用:

function doAdd(num1,num2){
    if(arguments.length == 1){
        alert(num1 + 10);
    }else if(arguments.length == 2){
        alert(arguemnts[0] + num2);
    }
}

还有一点。arguments的值永远与对应的命名参数保持同步:

function doAdd(num1,num2){
    arguments[1] = 10;
    alert(arguments[0] + num2);
}

  什么意思呢?就是每次执行这个函数时,里面的arguments[1]都会被设成10,对应的num2也会跟着变着10。

最后一点:没有传递值的命名参数将自动被赋予undefined,就像变量没有初始化一样。

关于函数定义时的参数,其实就像在函数内部定义的变量一样,只不过不用在显性的使用var来进行定义。

 

 posted on 2016-01-14 14:52  六人行与  阅读(4515)  评论(1编辑  收藏  举报