前言
整理完閉包與執行環境與一級函式後,我們確實地掌握到了這幾個名詞的基礎概念。但實際上如果曾經開發過 JavaScript ,在還不懂這些名詞的時候,或許已經無意間使用過這些技巧了,只是沒有意識到而已。像是如果使用過 setTimeout 或是 jQuery 事件,可能就使用過閉包。
閉包與回呼 (Closures And Callbacks)
像是 setTimeout 的小範例,使用了閉包與一級函式。
1 | function sayHiLater(){ |
setTimeout
接受兩個參數,一個是函式物件,一個為延遲執行時間。於是我們把一個匿名函式傳入,這是使用了 JavaScript 的一級函式觀念。
我們之前也討論過非同步過程、執行堆、 事件佇列的觀念,被包覆在 setTimeout
內的函式會先被放進事件佇列,等執行堆空了之後,才開始跑事件佇列裡的內容。
當開始運行 setTimeout
時,等到設定的時間過後便開始執行匿名函式,但 greet
不在函式裡,所以根據範圍鍊到外部環境尋找。
而雖然 sayHiLater
函式的執行環境已經不再執行堆內了,但是因為閉包,所以仍然可以取用 greet
變數。
像是 jQuery 的事件也使用到閉包與一級函式
1 | // $('button').click(function(){ |
這段程式碼將一個匿名函式當成參數傳入 jQuery 中的 click 函式,使其在進行 click 動作時會觸發這個匿名函式。
jQuery 就是這樣使用函式表示式和一級函式概念的。
回呼 (callback)
當某個函式執行完畢,要給該函式執行的函式,稱為回呼。
也就是說,我呼叫函式 a
,然後給它函式 b
,當函式 a
執行完畢時,呼叫函式 b
,也就是說它回呼了 b
函式,這就是回呼函式。
1 | function tellMeWhenDone(callback){ |
以這個例子來說,我們建立了一個 tellMeWhenDone
的函式陳述句,並且可以帶入一個 callback
的參數。
接著呼叫 tellMeWhenDone
函式,並傳入一個匿名函式給它,再 tellMeWhenDone
函式執行到 callback()
時,會呼叫我們傳給它的匿名函式,因此輸出就如同我們預計的那樣。