Closure這個詞有關閉、結束的意思,而閉包是JS一個重要觀念,非常難懂所以很多人不喜歡。
在JavaScript中每當函式被建立時,閉包就會被產生,是函式建立時就有的自然特性。雖然經常使用函式中的函式這樣的寫法,也就是巢狀函式的語法結構,是一種最常見、可被重複利用的閉包語法,但並不是只有巢狀函式才能產生閉包
函式可以
先來看看以下範例:
因為函式就是物件,所以可把它當成一個值回傳,
function data(text) {
return function(name) {
console.log(text+ '' + name)
}
}
但這時要如何呼叫函式? 雖然這看起來有點怪
呼叫一個回傳函式的函式data時,同時呼叫那個被回傳的函式(阿 好像在繞口令)
data('hello')('joyce');
//打開console就可以看到:
//hello joyce
function data(text) {
return function(name) {
console.log(text+ '' + name)
}
}
//設定一個變數為函式的回傳值
var sayHi = data('Hi')
//呼叫sayHi,執行這段,仍然可以執行
sayHi('Tommy') //Hi Tommy
當在執行sayHi的時候 因為是閉包所以text參數在data函式被呼叫的時候
仍然可以被使用,
在執行這段函式時,是全域的執行環境
1.到了var sayHi = data
這行時,呼叫了data
2.這時,新的執行環境被創造了
3.text參數被傳入到data的環境裡
4.然後再回傳一個新的物件函式
5.回傳之後,data的執行環境就離開了執行堆
6.這個data執行堆就不見了
但這裡有個問題!
每個執行環境都有自己的記憶體空間,參數和函式都被創造在裡面,那當執行環境沒了之後記憶體空間會怎麼樣呢?在一般情況下,JS引擎會清除它,這動作稱為垃圾回收,但是當執行環境結束時,記憶體空間仍然存在即使執行環境已經沒了但它還在記憶體某處。
也就是說:
data已經沒了執行環境,但在記憶體中還在,只是不在執行堆裡,但是執行環境可以把它的外部變數關住、包住,所以可以取用到的現象稱為閉包
所以JS永遠會確保無論我在執行哪個函式,都能取用該要用到的變數是JavaScript重要且強大的特色
參考: udemy-克服 JS 的奇怪部分