內部函數總是可以訪問其所在的外部函數中聲明的參數和變數,即使外部函式已經結束執行了。
看看這個例子:
EX:
function greet(what){
return function(name){
console.log(what+" "+name);}
}
var aa=greet('Hi');
aa('Ivy');
// Hi Ivy
外面的greet函式已經被呼叫並執行完畢了,為甚麼裡面回傳的函數還知道greet傳進來的'Hi'?彷彿外面的函數以及變數what還在一樣。
因為當greet函數被呼叫,新的執行環境被創造而且what參數被傳入,存進greet函數的變數中。
然後很快地創造一個物件函數,回傳之後greet的執行環境馬上離開執行堆。
但問題來了,每個執行環境都有他的記憶體空間,一般來說,當執行環境沒了之後記憶體空間會被JavaScript引擎回收。
但是在這裡,記憶體空間還在。
而下面呼叫aa,另一個新的執行環境被創造,在這個函數裡面想要找 what 變數找不到,就往更外一層找,就算greet的執行環境沒有了,aa 還是可以參考到 greet函數的變數,在aa外部環境的記憶體空間,即使greet執行環境已經離開執行堆。
如圖:
執行環境可以把它的外部變數關住、包住,以確保函數可以取用外部變數的現象 稱為閉包。
參考資料:
MDN 閉包
閉包,看這一篇就夠了——帶你看透閉包的本質,百發百中
阮一峰的網路日誌 學習Javascript閉包(Closure)