search

Home  >  Q&A  >  body text

javascript - 这段代码不是很理解?为什么最后输出10

javascriptfunction constfuncs() {
    var funcs = [];
    for (var i = 0; i < 10; i++) {
        funcs[i] = function () {
            return i;
        }
    }
    return funcs;
}
var funcs = constfuncs();
alert(funcs[1]());
funcs[1]()  这个是什么意思?
巴扎黑巴扎黑2819 days ago562

reply all(9)I'll reply

  • PHPz

    PHPz2017-04-10 15:09:29

    如果你想得到你“想象中”的结果,需要用闭包。

    这题里,你的每一个funcs[i]都声明了一个函数,但是函数都没有被立刻执行,而是排进了队列。

    但是你的for循环是一直在执行的,等10个函数声明完毕,i也走完了,就是说i现在的值是10。

    这时,你调用funcs[1]()去执行你之前声明的函数,因为现在i是10,所以理所应当的返回10。

    如果你想得到“正确”的结果,需要用闭包改写:

    function constfuncs() {
        var funcs = [];
        for (var i = 0; i < 10; i++) {
            funcs[i] = (function () {
                return i;
            }(i))
        }
        return funcs;
    }
    var funcs = constfuncs();
    console.log(funcs[1]);
    

    用闭包保存i,这样你最后返回的值才会是你输入的值i。

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 15:09:29

    这是个闭包的问题。
    funcs[1]是一个函数,返回的值是 i。funcs[1]() 就是运行这个函数。
    对于外部 constfuncs来说,下面这个就是个闭包。

    javascriptfuncs[i] = function() {
        return i;
    }
    

    《JS高级程序设计》p.181 就是这个例子。

    闭包保存的是整个对象,而不是特殊变量

    每个funcs[n]里面引用的都同一个变量 i ,所以最后的返回值是一样的。

    我把题中的函数改了改,为了方便显示,i 就改成了3。楼主看图感受下,应该就明白了。

    reply
    0
  • PHPz

    PHPz2017-04-10 15:09:29

    首先,
    funcs是生成了10个function对象的数组,每个节点都是一个

    javascriptfunction () {
       return i
    }
    

    但这里有个bug,这里的i其实都是引用了var i;所以闭包里面i都是指向同一个i;
    解决的话,需要一个自执行的方案,

    javascript
    function constfuncs() { var funcs = []; for (var i = 0; i < 10; i++) { funcs[i] = (function (e) { return e; })(i); } return funcs; } var funcs = constfuncs(); alert(funcs[1]());

    我知道 let 也能解决。

    javascriptfor (let i = 0; i = 0; i < 10; i++) {
    ...
    }
    

    也能解决,不知道是不是所有浏览器都支持

    回答的瞬间就有三个答案了

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 15:09:29

    function constfuncs() {
        var funcs = [];
        for (var i = 0; i < 10; i++) {
            funcs[i] = (function (i) {
                return function(){
                    return i;
                };
            }(i))
        }
        return funcs;
    }
    var funcs = constfuncs();
    console.log(funcs[1]());
    

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 15:09:29

    闭包内捕获的变量是一个引用,而不是当时变量值的快照,相反的,函数参数中的参数传递传递的是变量的值。题目中的源代码里,闭包捕获到的是变量i的引用,始终指向变量i,i的值在循环式的最后变为了10,所以所有函数的返回值均为10。

    以下代码就是一个返回当时变量i的值的快照的形式。在函数createFunc的参数传递中对变量i的值进行了拷贝。

    function constfuncs() {
        var funcs = [];
        for (var i = 0; i < 10; i++) {
          function createFunc(i) {
            return function() {
              return i;
            };
          }
          funcs[i] = createFunc(i);
        }
        return funcs;
    }
    var funcs = constfuncs();
    alert(funcs[1]());
    

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 15:09:29

    这就是个闭包呀,犀牛书上的例子。
    var funcs = constfuncs();
    constfuncs()运行这个函数,并将return结果返回给funcs。
    过程:1. 新建数组,同时for循环生成一个函数数组。每个函数数组中属性都是function(){return i};
    2. for循环结束。此时i=10.
    3. rerurn 这个函数数组给funcs。此时funcs是一个函数数组。
    注意:第一步中,循环只是把这些函数function(){return i}放进数组中,这些函数本身是没有运行的。
    第三步是funcs是这个函数数组的外部引用,所以,constfuncs这个函数的作用域对象,没有当做垃圾被回收。
    alert(funcs[1]());
    过程: 1.运行这个函数数组中第二个函数, 此时function(){return i}
    2.在运行function(){return i}时。i的循环已经结束了。而且i的值为10.所以此时运行结果就是返回一个数字10。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 15:09:29

    funcs是一个数组,数组元素个数为10个,每个元素都是函数

    function () {
        return i;   //for循环完结后,i的值为10.
    }
    

    funcs[1]表示第一个元素,即以上的函数
    funcs[1]()表示执行函数。函数返回值为10,所以输出10

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 15:09:29

    考察了闭包的概念

    reply
    0
  • 阿神

    阿神2017-04-10 15:09:29

    内部funcs[i]形成闭包,与循环构成异步,循环瞬间执行完,内部的闭包待循环执行完之后才拿到值,当然就是10咯

    reply
    0
  • Cancelreply