搜索

首页  >  问答  >  正文

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

大家讲道理大家讲道理2765 天前699

全部回复(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 已经结束,因此取 for 已经结束,因此取 i 的时候值是 5 的时候值是 5

    回复
    0
  • 取消回复