function box() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function () {
return i;
}
}
return arr;
}
var b = box();
for (var i = 0; i < 5; i++) {
alert(b[i]);
}
當box()執行完之後,為什麼arr[0]到arr[4]裡面的值都是function () { return i;}
為什麼不依序是:function () {return 0;} ,function () {return 1;}。 。 。
因為閉包只能取得包含函數中任何變量的最後一個值,在這裡指的就是i這個變量,box()函數執行後返回的是一個函數數組,數組中的每一個i引用的都是同一個變數i,注意box()回傳的是一個函數!所以裡面的{return i}這只是函數內的一個聲明,還沒有執行呀,所以當然保持{return i}不變。因為引用的是同一個外部i,所以當box()函數返回後,外部變數i的值是5,此時每一個return中都引用著保存變數i的同一個變數對象,所以如果最後執行了內部的arr[]中的函數,最後每個函數內部的i的值都是5.
因為關聯到閉包的作用域鍊是"活動的". 並且他們共享變數i , 並不是對每個綁定的變數的值賦值自己單獨的一份. 他們只是引用i,並不會保存i 每個階段的值.
參考書籍: JavaScript 權威指南 8.6 小節.
雷雷
雷雷
範例中for循環裡的function只是賦值,並沒有執行,所以當數組中函數執行時才去獲取i的值,這時候i只有循環結束的值,樓上沒有用到閉包,只是用一個立即執行的匿名函數得到了每個循環的i的值;
方法:1.用ES6 let取代var
function box() {
2.採用閉包
function box() {
。 「閉包」 一詞來自以下兩者的結合:要執行的程式碼區塊(由於自由變數被包含在程式碼區塊中,這些自由變數以及它們引用的物件沒有被釋放)和為自由變數提供綁定的運算環境(作用域) ---百度百科
意思是
這個就是一個程式碼塊,作用只是他引用了i,這樣持有i就會導致i不會被釋放掉,我們保存的只是這個程式碼塊,這個程式碼塊不運行之前,他根本不知道i是什麼東西,就有他運行的時候,他才會去找i,所以你可以把你的arr都輸出一下,應該輸出的全是5
呼叫的時候才計算
i
是什麼。而在呼叫這些函數的時候,
for
已經結束,因此取i
的時候值是5