JavaScript 函数表达式

 1.   在JavaScript中定义函数的方式有两种,一种是函数声明,另一种就是函数表达式。

    函数声明的方法如下: 

function functionName(arg0, arg1....){
  函数体  
}

  首先是关键字function,然后是函数的名字,这就是函数声明。 关于函数声明有一个非常重要的特征,就是在执行代码之前会先读取函数声明,这就意味着你可以把函数声明放在调用他的语句之后。如下:

  

1 test();
2 function test(){
3   alert('Hello world!');  
4 }

这样不会出什么错误,因为执行代码之前已经读取了函数声明。

    函数表达式中最常见的一种形式如下:

var functionName = function(){
   函数体  
}

    这种函数表达式看起来像是变量赋值语句,即创建了一匿名函数并将它赋值给了functionName。之所以说一创建了一个匿名函数,那是因为关键字function后面没有名字。

 既然是表达式,那么在使用它之前必须要先赋值,以下代码将会报错:

 

test();
var test = function(){
   alert("Hello world!");
}

  函数表达式与函数声明的最大区别就是函数声明的提升,就是说函数声明可以在执行之前已经读取到了内存中。看下面的代码:

         if(condition){
             function demo(){
                 alert("Hello");
             }
         }else{
             function demo(){
                 alert("Ni hao!");
             }
         }

  表面看上去,当condition为true的时候使用一个demo的定义,为fale的时候使用另外一个定义,但是实际上这是一种无效的语法,在严格模式'use strict'下甚至还会报错。

因为在执行之前已经读取了函数声明,所以大多数浏览器则会第二个覆盖了第一个函数声明。但是如果用函数表达式就没有什么问题了。

2. 递归

    递归函数在函数调用自身的情况下形成的,如下代码: 

function factorial(num){
    if(num <= 1){
        return 1;
    }else{
        returm num * factorial(num - 1);
    }

}

这是一经典的递归阶乘函数。虽然看起来没什么问题,但是在下面代码执行的时候就会报错。

var test= factorial;
factorial = null;
test(4);

因为在递归函数中会再次调用factorial这个function,但是factorial已经为null了所以会报错。 所以在这种情况下推荐使用arguments.callee, 如下代码

function factorial(num){
    
      if(num <= 1){
           returm 1;
      }else{
          return num * arguments.callee(num -1);
     }
}

我们知道arguments,每一function中都会有这个变量,代表了每一function中的参数,例如arguments[0] 表示传过来的第一参数,arguments[1] 表示传过来的第二个参数,以此类推。而arguments.callee表示的是一个当前正在执行的函数的指针,即指向当前执行的函数,因此他可以实现递归函数。但是这种语法在严格模式'use strict'下, 这种方法会报错。不过还有一种方式,函数表达式的方式来表示递归,严格模式下也不会报错,如下

var factorial = (function fn(num){
       if(num <= 1){
            return 1;
       }else{
           return num * fn(num -1);
       }

});

3. 闭包

    什么是闭包呢? 闭包是有权访问一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建一个函数并返回。如下:

 

function createFactory(name){
    
    return function(object1, object 2){
        var value1 = object1[name];
        var value2 = object2[name];
       return vale1 - value2;
   }
}    

在上面的代码中反回了一个匿名函数,在匿名函数中访问了外部函数中的变量name。 这个匿名函数被返回了,而且就在算在其他的地方调用也可以访问到name,不会报错,这是因内部函数的作用域链中包含外部函数createFactory的作用域链。什么是作用域链呢? 每一个函数执行的时候都有自己的执行环境,当执行一个函数的时候,函数就会被放到一个环境栈中,执行完之后,栈将其弹出,并把控制权交给之前的函数。当代码在一个环境中执行的时候,会创建变量对象的一个作用域链。作用域链保证了对当前执行环境的变量的有序访问。

明天继续。

 

posted on 2016-12-06 00:23  xiaodong135  阅读(370)  评论(0编辑  收藏  举报

导航