2016年5月26日

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


在上一次的筆記中([筆記] 談談JavaScript中closure的概念 -- Part 2),我們用進階的例子進一步的說明了closure的概念,那如果我們想要讓上一篇文章中的程式碼,輸出的結果是0, 1, 2的話,我們可以怎麼做呢?

原本的程式碼是這樣子,而且會輸出3, 3, 3的結果:


如果我們要讓他輸出的結果變成 0, 1, 2,我們可以這樣做。

方法一:使用LET


在最新的ES6(ECMAScript 6)中,我們可以使用關鍵字 let 來達到這樣的效果。透過let,可以讓每次跑的迴圈都建立到一個新的記憶體位置,因此最後指稱到的地方會是不一樣的,於是可以輸出0, 1, 2的結果。


方法二:在呼叫陣列的時候即執行函式


如果我們的瀏覽器還不支援ES6的話,我們可以讓這段程式在將function寫進陣列的時候,就加以執行這段function,也就是迴圈每跑一次,就執行一次function。記得我們要怎麼樣可以直接在function建立的時候就加以執行函式嗎?

沒錯,就是先前我們提到的IIFEs

所以我們可以寫成這樣:


不得不說,這段程式碼看起來實在是有點複雜。讓我們來了解一下:

首先,當執行buildFunctions的時候,陣列裡面的匿名函式 function(j){...}這段因為是IIFEs,所以會直接被執行,並且把變數 i 帶入函式中,於是,當我們在執行 fs[0]( ) 的時候,因為在fs[0]( )的execution context中,已經存有變數 j ,所以當我們執行 fs[0]( ) 的時候,就可以得到0的結果。其他fs[1]( )和fs[2]( )的部分,也是以此類推。


程式範例

function buildFunctions(){
 
 var arr = [];

 for(var i = 0; i < 3; i++){
  arr.push(
   (function(j){
    return function(){
     console.log(j);
    };
   }(i))
  )
 }
 
 return arr;
}


var fs = buildFunctions();
fs[0](); // 0
fs[1](); // 1
fs[2](); // 2
→回到此系列文章目錄

0 意見:

張貼留言