1. 閉包的概念 據我們所知,局部變數在函數退出之後就不占據記憶體空間,但存在一種特殊的函數,能使局部變數在函數退出之後繼續占據記憶體,為外部函數所調用,這個特殊的函數就是 。那麼閉包是怎麼做到將局部函數一直占據記憶體的呢?看看下麵的例子。 function a(){ var Aitem=2;//定義局部 ...
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)的局部變數。如果沒有將內部函數裝化成全局變數的話,就形不成閉包,請看下麵的例子:
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也無從獲取。
3. 總結
閉包是可以讀取其他函數內部變數的函數,是外部函數和內部函數的一座橋梁。
閉包擁有兩個作用:
- 使局部變數keep alive
- 讀取其他函數的局部變數