Javascript 的閉包

1. 閉包的概念

據咱們所知,局部變量在函數退出以後就不佔據內存空間,但存在一種特殊的函數,能使局部變量在函數退出以後繼續佔據內存,爲外部函數所調用,這個特殊的函數就是閉包。那麼閉包是怎麼作到將局部函數一直佔據內存的呢?看看下面的例子。閉包

function a(){
    var Aitem=2;//定義局部變量item
    function b() { //定義內部函數b()
        alert(Aitem);
    }
    b();
}
a();//結果是2
複製代碼

2. 閉包的機理

從上能夠看出內部函數能夠讀取外部函數的局部變量。此時的內部函數的做用域僅限於外部函數a(),只有經過調用外部函數a()才能夠運行內部函數b()。當外部函數執行結束,內部函數的內存也將清除。可是若是咱們將內部函數賦給一個全局變量,那麼內部函數將從局部變量轉化成全局變量。即便外部函數退出了,做爲全局變量的內部函數也將保存在內存中。那麼如何讓內部函數成爲全局變量呢?函數

function a(x){
    var Aitem=2;//定義局部變量item
    return function b(y) { //a函數結果返回一個b函數
        alert(x+y+(++Aitem));
    }
}
var closure=a(1);//將a(1)return的結果b()賦給全局變量,closure=b(y){ alert(1+y+(++Aitem))}
closure(1);//彈出5;closure(1)=b(y){ alert(1+1+(++2))}
closure(1);//彈出6;closure(1)=b(y){ alert(1+1+(++3))}
複製代碼

上例中的closure()函數即閉包。第一次closure(1)中Aitem=2,第二次closure(1)中Aitem=3,能夠看出item這個局部變量在a()退出之後並無被清除,而是像一個全局變量同樣一直保存在內存中。這就是閉包的神奇所在。closure()閉包依賴於b(y),而b(y)又是a(x)的局部函數,故closure()閉包能夠實時訪問a(x)的局部變量。若是沒有將內部函數裝化成全局變量的話,就形不成閉包,請看下面的例子:spa

function a(x){
    var Aitem=2;//定義局部變量item
    function b(y) { //定義局部函數b
        alert(x+y+(++Aitem));
    }
     b(1);//在a()內部運行b(1);即alert(x+1+(++2))
}
a(1);//彈出5;即alert(1+1+(++2))
複製代碼

上例沒有將局部函數b()賦給全局變量,在a(1)運行之後b()就不復存在,Aitem也無從獲取。code


3. 總結

閉包是能夠讀取其餘函數內部變量的函數,是外部函數和內部函數的一座橋樑。內存

閉包擁有兩個做用:作用域

  • 使局部變量keep alive
  • 讀取其餘函數的局部變量

閉包的缺點:it

  • 常駐內存,形成內存的浪費
相關文章
相關標籤/搜索