1. 程式人生 > >對js閉包的理解

對js閉包的理解

閉包的基本理解

閉包是什麼?相信很多初學JS的人一定對這個概念比較模糊,我也是看了很多部落格和書籍才稍微瞭解了一點。因為閉包的應用非常廣泛,在js程式碼裡基本可以說是隨處可見,所以想要學好js,閉包是必須要掌握的。不過在瞭解閉包之前,首先要了解JS的全域性變數,區域性變數和作用域鏈,關於作用域鏈可以參考這篇部落格http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

在瞭解作用域鏈之後,就開始學習閉包吧

我們在定義區域性變數的時候一定要記得var命令,如果沒有這個,宣告出來的變數就是全域性變數。

  function
f1(){
  n=1;   }   alert(n); // 1

上面程式碼等同於

  var n=1;
  function f1(){
  }
  alert(n); // 1

因為js的函式內部可以直接訪問到外部的變數

  var n=1;
  function f1(){
      alert(n); // 1
  }

外部就不能訪問內部的變數

  function f1(){
      var n=1;
  }
  alert(n); // error

閉包就是能使外部訪問其他函式內部的函式,舉一個閉包的簡單例子吧

  function a(){
        var
i=0; function b(){ alert(++i); } return b; } var c = a(); c(); // 1

這段程式碼有兩個特點:
1、函式b巢狀在函式a內部;
2、函式a返回函式b;
這樣在執行完var c=a()後,變數c實際上是指向了函式b,再執行c()後就會彈出一個視窗顯示i的值(第一次為1)。這段程式碼其實就建立了一個閉包,為什麼?因為函式a外的變數c引用了函式a內的函式b,就是說:
當函式a的內部函式b被函式a外的一個變數引用的時候,就建立了一個閉包。
簡而言之,閉包的作用就是在a執行完並返回後,閉包使得Javascript的垃圾回收機制GC不會收回a所佔用的資源,因為a的內部函式b的執行需要依賴a中的變數。
在上面的例子中,由於閉包的存在使得函式a返回後,a中的i始終存在,這樣每次執行c(),i都是自加1後alert出i的值。
用閉包可以解決很多問題,如

  function a(){
      var result = new Array();
        for(var i=0;i<10;i++)
        {
            result[i]=function(){
                return i;
            }
        }
        return result;
    }

這個函式會返回一個函式陣列,表面上看每個函式都應該返回自己索引值,也就是位置0的時候返回0,1的時候返回1。但實際上每個函式都返回的是10,因為每個函式的作用域鏈裡都儲存這a()函式的活動物件,所以他們引用的都是同一個變數i,當函式a()返回後,i的值為10,此時每個函式都儲存這同一個變數i,所以每個函式內部i的值都是10,用閉包的解決方法如下:

  function a(){
      var result = new Array();
        for(var i=0;i<10;i++)
        {
            result[i]=(function(i){
                return function(){
                    return i;
                };
            })(i);
        }
        return result;
    }