2016年5月30日

[筆記] 談談JavaScript中closure的概念 -- Part 4 Framework中如何使用closure


在看過前面有關於closure的說明後,不知道你對於JavaScript中closure的概念是不是更清楚了?

[筆記] 談談JavaScript中closure的概念 -- Part 1
[筆記] 談談JavaScript中closure的概念 -- Part 2
[筆記] 談談JavaScript中closure的概念 -- Part 3

在這篇文章中,我們來看看在Framework中可以怎麼樣使用closure這樣的概念。

讓我們先來看下面這段程式碼,

我們先建立了一個makeSayHi的function,而這個function會回傳另一個匿名函式 return function(name){...} ,這個匿名函式則會根據makeSayHi的參數language來回傳不同的內容:


接著,我們分別將兩個不同language參數而回傳的function存成兩個變數,並且加以呼叫:


看過前幾個Closure概念後,你是不是可以知道,這樣會ouput出什麼樣的結果呢?

結果如下,和你想的一樣嗎?


解讀程式


讓我們再次試著了解這段程式的內容。

首先,由於hoisting的緣故,makeSayHi( ), SayHiEnglish, SayHiChinese會先被儲存在記憶體中,接著才開始逐行執行程式碼:


當程式執行到 var SayHiEnglish = makeSayHi('en') 時,makeSayHi的execution context被建立,同時將變數language的值'en'儲存在這個execution context中


接著,會回傳makeSayHi裡面的匿名函式,並儲存到SayHiEnglish這個變數中。執行完後makeSayHi的execution context就抽離了,但language參數的值"en"仍然被儲存在記憶體中:


接著,程式會執行到 var SayHiChinese = makeSayHi('zh') ,這時候我們會再次執行makeSayHi這個函式,雖然執行的是同樣makeSayHi這個函式,但實際上會產生新的一個execution context,也就是說,你每執行一次函式,就會產生一個新的execution context


接著,一樣會將回傳的匿名函式儲存在SayHiChinese中,makeSayHi的execution context再次抽離,並留下language的參數:


將函式都儲存到變數後,會執行 SayHiEnglish('PJCHEN') ,這時,SayHiEnglish會被執行,並代入name變數的值"PJCHEN",這時候在記憶體中有兩個language參數的值被儲存著,一個是zh, 一個是en,而JavaScript引擎會自己找到它所對應的參數值,並形成所謂的closure。


同樣的情形會在程式執行到 SayHiChinese('PJCHEN') 發生,於是再次形成了一個新的closure。


整個程式執行的流程大概就是這樣子。這裡的重點在於每執行一次函式,就會產生一個新的execution context,而且即使有多個參數值被儲存在記憶體中,JavaScript引擎會自己找到屬於該execution context的變數。

程式範例

function makeSayHi(language){

 return function(name){
  if(language === 'en'){
   console.log('Hello ' + name);
  }

  if(language === 'zh'){
   console.log('你好 ' + name);
  }
 }

}

var SayHiEnglish = makeSayHi('en');
var SayHiChinese = makeSayHi('zh');

SayHiEnglish('PJCHEN');
SayHiChinese('PJCHEN');
→回到此系列文章目錄

0 意見:

張貼留言