搜尋

首頁  >  問答  >  主體

javascript - 初學閉包,不太明白,求大神指教

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;}。 。 。

大家讲道理大家讲道理2750 天前692

全部回覆(7)我來回復

  • 学习ing

    学习ing2017-06-26 11:00:00

    因為閉包只能取得包含函數中任何變量的最後一個值,在這裡指的就是i這個變量,box()函數執行後返回的是一個函數數組,數組中的每一個i引用的都是同一個變數i,注意box()回傳的是一個函數!所以裡面的{return i}這只是函數內的一個聲明,還沒有執行呀,所以當然保持{return i}不變。因為引用的是同一個外部i,所以當box()函數返回後,外部變數i的值是5,此時每一個return中都引用著保存變數i的同一個變數對象,所以如果最後執行了內部的arr[]中的函數,最後每個函數內部的i的值都是5.

    //执行内部返回的arr中的函数,当然box()[1]()、box()[2]()、box()[3]()...都返回5;
        function box() {
            var arr = [];
            for (var i = 0; i < 5; i++) {
                 arr[i] = function () {
                    return i;
                }
            }
            return arr;
        } 
        box()[1](); //执行后返回5
    
    //不执行内部函数,仅仅是box()的话,当然只返回一个function咯
        function box() {
            var arr = [];
            for (var i = 0; i < 5; i++) {
                 arr[i] = function () {
                    return i;
                }
            }
            return arr;
        } 
        box(); //[function, function, function, function, function]
    

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-06-26 11:00:00

    因為關聯到閉包的作用域鍊是"活動的". 並且他們共享變數i , 並不是對每個綁定的變數的值賦值自己單獨的一份. 他們只是引用i,並不會保存i 每個階段的值.

    參考書籍: JavaScript 權威指南 8.6 小節.

    回覆
    0
  • 淡淡烟草味

    淡淡烟草味2017-06-26 11:00:00

    雷雷

    回覆
    0
  • 世界只因有你

    世界只因有你2017-06-26 11:00:00

    雷雷

    回覆
    0
  • 阿神

    阿神2017-06-26 11:00:00

    範例中for循環裡的function只是賦值,並沒有執行,所以當數組中函數執行時才去獲取i的值,這時候i只有循環結束的值,樓上沒有用到閉包,只是用一個立即執行的匿名函數得到了每個循環的i的值;
    方法:1.用ES6 let取代var
    function box() {

        var arr = [];
        for (let 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]());
    }

    2.採用閉包
    function box() {

        var arr = [];
        for (var i = 0; i < 5; i++) {
            arr[i] = function (x) {
                return function(){
                    return x;
                };
            }(i);
        }
        return arr;
    }
    var b = box();
    for (var i = 0; i < 5; i++) {
        alert(b[i]());
    }

    回覆
    0
  • 我想大声告诉你

    我想大声告诉你2017-06-26 11:00:00

    。 「閉包」 一詞來自以下兩者的結合:要執行的程式碼區塊(由於自由變數被包含在程式碼區塊中,這些自由變數以及它們引用的物件沒有被釋放)和為自由變數提供綁定的運算環境(作用域) ---百度百科
    意思是

    function () {
                    return i;
                }

    這個就是一個程式碼塊,作用只是他引用了i,這樣持有i就會導致i不會被釋放掉,我們保存的只是這個程式碼塊,這個程式碼塊不運行之前,他根本不知道i是什麼東西,就有他運行的時候,他才會去找i,所以你可以把你的arr都輸出一下,應該輸出的全是5

    回覆
    0
  • 我想大声告诉你

    我想大声告诉你2017-06-26 11:00:00

    // arr的元素均是下面这个函数 
    function(){
        return i; 
    }

    呼叫的時候才計算 i 是什麼。

    而在呼叫這些函數的時候,for 已經結束,因此取 i 的時候值是 5

    回覆
    0
  • 取消回覆