前言
前面提到了閉包,也講解了一些典型的範例,而閉包還有很多有用的地方。在這篇文章中,我們會談到如何利用閉包來建立函式工廠 (Function Factories),讓程式的撰寫上能更靈活,減少累贅的程式碼,這個技巧常常可在一些知名框架內看到。
Function Factories
我們在重載函式那一篇知道,可以有一些做法讓函式可以在不同情況下被不同的預設參數呼叫。因為我們已經了解閉包,所以我們將要使用閉包的概念讓這個範例更完善。
1 | function makeGreetFactory(languaue){ |
- 建立一個會回傳函式的
makeGreetFactory
函式,並可以帶入languaue
參數。 - 被回傳的匿名函式可以帶入
firstName
、lastName
並且依據languaue
有不同的打招呼方式。
注意到不同的地方了嗎?
原本我們是將 languaue
傳入到匿名函式內,這次改成傳到外部函式,利用閉包的概念去完成。
接著宣告
greetEnglish
變數,指向makeGreetFactory
函式並帶入languaue
的參數值 「en」。- 當 JavaScript 運行到這一行時,每當
makeGreetFactory
被呼叫就會建立一個執行環境,以這個執行環境來說,languaue
為 「en」。
- 當 JavaScript 運行到這一行時,每當
同理,宣告 greetSpanish 變數,呼叫 makeGreetFactory ,此時又建立一個執行環境,以這個執行環境來說,
languaue
為 「es」。- 因此,當我呼叫
greetEnglish()
時,因為閉包的關係,即使makeGreetFactory
函式不再執行堆裡,變數languaue
仍可被取用。
- 因此,當我呼叫
而
greetEnglish()
對應的閉包範圍languaue
值為「en」
同理greetSpanish()
對應的閉包範圍languaue
值為「es」
白話說 Function Factories
以這個例子來說, makeGreetFactory
函式就像一個箱子工廠,而傳入的 languaue
可以理解成不同種類的箱子。
然後我跟這個工廠說,我要一個種類為「en」的箱子,於是我得到了一個在外部寫有「en」字樣的箱子,並且裡面裝有一個會參考到這個箱子外部寫了什麼種類的函式。
使用圖例幫助了解閉包範圍
最後要強調的是,每當呼叫函式,函式會得到專屬於它的執行環境,然而在這個執行環境內被創造的函式會指向這個執行環境(注意創造不等於呼叫)。