1.2.3.18.了解閉包(二)
應用閉包的實際案例
1 function buildFunctions() { 2 var arr = []; 3 for (var int i = 0; i < 3; i++){ 4 arr.push( 5 //Only create function 6 function () { 7 console.log(i); 8 } 9 ) 10 } 11 return arr[i]; 12 } 13 var fs = buildFunctions(); 14 //執行時會找到i 15 //印出3 16 fs[0](); 17 //印出3 18 fs[1](); 19 //印出3 20 fs[2]();
執行程式
行 1 ~ 12: 全域執行環境 (global Execution context)被建立, 並存放buildFunctions(),fs
行 13: 建立新的執行環境, 待函數執行完後回傳 i =3, arr = [f0, f1, f2]
行7不會被執行
buildFunctions 的執行環境離開執行堆, 但執行環境的記憶體還會在, 因此i, arr還在
行16 ~ 20被執行, 這時候因為函數中沒有i, arr的定義, 根據範圍鍊的觀念會開始向外尋找, 此時還是找的到i, arr, 因為i, arr位於外部的記憶體位置
如何正常印出i?
解法1:
加入行4: 因為變數j會在迴圈中, 在記憶體中建立一個新的
1 function buildFunctions2() { 2 var arr = []; 3 for (var int i = 0; i < 3; i++){ 4 let j = i; //es6的語法 5 arr.push( 6 //Only create function 7 function () { 8 console.log(i); 9 } 10 ) 11 } 12 return arr[i]; 13 } 14 var fs2 = buildFunctions2(); 15 //執行時會找到i 16 //印出3 17 fs2[0](); 18 //印出3 19 fs2[1](); 20 //印出3 21 fs2[2]();
解法2:
IIFE: 立即執行
行 6 ~ 20會立即執行, 此時行7會回傳匿名函數 j的值會在迴圈執行時儲存
當匿名函數執行時, 會尋找j
1 function buildFunctions2() { 2 var arr = []; 3 for (var int i = 0; i < 3; i++){ 4 arr.push( 5 (function (j) { 6 return function() { 7 console.log(j); 8 } 9 }(i)) 10 ) 11 } 12 return arr[i]; 13 } 14 var fs2 = buildFunctions2(); 15 //執行時會找到i 16 //印出3 17 fs2[0](); 18 //印出3 19 fs2[1](); 20 //印出3 21 fs2[2]();
Last updated
Was this helpful?