JavaScript: Function(函数)

@ 2010-09-16 17:58:59
标签:

    一个函数,有名字,有参数,有返回值。函数是代码重用的最常见方式。

    函数的声明和定义

    先看一段代码:

    function max(a,b){          // Method (1) : function statement
      return Math.max(a,b);
    }
    
    alert(typeof(window.max));  // == function
    
    var max = function(a,b){    // Method (2) : function expression
      return Math.max(a,b);
    };
    
    alert(typeof(window.max));  // == function
    alert(max(3,4));            // works well
    
    max = function my_max(a,b){ // Method (3)
      return Math.max(a,b);
    };
    
    alert(typeof(window.max));  // == function
    alert(max(3,4));            // works well
    
    alert(typeof(my_max));      // == undefined
    

    第一种函数声明方法是最基本的方法。并且我们注意到函数名'max'成了全局对象window的一个属性。事实上,第一种声明方法和第二种方法是等效的。第三种声明方法跟第二个相比,只多了一个函数名'my_max',并且我们注意到'my_max'在的代码中却是 undefined。因此,对于JavaScript中的函数有以下一些事实:

    • 函数实际上是Function Object的一个实例
    • 函数名的作用域只在函数体内有效
    • 直接声明一个函数,实际上等效于把这个函数赋值给了同名变量

    函数的参数

    JavaScript的函数支持可变长度参数。函数定义时的参数列表本质上不过是给参数提供了一个别名。

    function max(a){ return Math.max(a, arguments[1]); }
    
    alert(max());       // = NaN
    alert(max(1));      // = NaN
    alert(max(2,3));    // = 3
    alert(max(4,5,6)); // = 5
    

    上面代码中函数'max'定义时参数列表中只有一个参数'a',但在调用时却可以接受任意个参数。事实上,JavaScript中函数的参数只跟叫做 arguments的对象实例有关。

    arguments 对象

    arguments 可以看作一个数组,这个数组包含了传递给函数的所有参数。但它实际上不是一个数组(Array)。比如,它并没有 pop这个方法。arguments除了 length 属性用来标识参数的数目,还有一个 callee属性用来指向当前正在执行的函数。

    callee有什么用呢?也许唯一的用法就是实现一个匿名的递归调用函数。下面是 MDC 上的例子:

    function makeFactorialFunc() {
       alert('making a factorial function!');
       return function(x) {
          if (x <= 1)
             return 1;
          return x * arguments.callee(x - 1);
       };
    }
    
    var result = makeFactorialFunc()(5); // returns 120 (5 * 4 * 3 * 2 * 1)
    

    Function Object

    上面有提到,每个function都其实是一个Function Object的实例。因此,我们也可以通过Function对象来创建一个函数。比如:

    var max = new Function('a', 'b', 'return Math.max(a,b);');
    

    这和上面利用 'function'语句来定义函数达到的效果是一样的。但却给动态定义函数提供了可能。

    在函数定义之前调用函数

    如果函数是通过function statement的方式来定义的话,是可以在函数定义之前调用该函数的。下面的例子同样来自 MDC,是可以运行的。

    foo(); // works well
    
    function foo() {alert('FOO!'); }
    

    call & apply

    Function 对象有两个特别的方法,callapply。这两个方法可以给函数传递一个对象作为this指针。两者的不同只是在于函数参数传递方法的不同。

    function print(a,b){  alert(this.name +', ' + a + b)}
    
    print.apply({name:'Sean'},[1,2]);  // OK
    print.call({name:'Sean'},3,4);  // OK 
    print.apply({name:'Sean'},5,6); // 错误。apply 要求传递的参数以数组形式出现
    

    参考资源

    标签:

      分享到:
      comments powered by Disqus

      19/21ms