比如: 
function A() {
     var result = [];
     for (var i = 0; i < 3; i++)
         result.push( function(){ console.log( "item " +i);});
     return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
    a[i]();
}//item 3 item 3 item 3为什么调用的是同一个闭包~

解决方案 »

  1.   

    你这压根就没闭包。function A() {
         var result = [];
         for (var i = 0; i < 3; i++)
             result.push((function(i){ return function(){console.log( "item " +i)};})(i));
         return result;
    }
    var a = A();
    for (var i = 0; i < 3; i++) {
        a[i]();
    }
    仔细看看你push的时候跟我push的时候有什么不一样。
      

  2.   

    那  我上面那个算什么? 就是push了一个function对象吗?  为什么打印出来一只都是 i = 3
      

  3.   

    你是push 了一个function,但是对于这个function他访问到的i永远是A方法里循环结束后的i
      

  4.   

    因为你的代码所有添加进数组中的function都处在同一个闭包的作用域里面。这个作用域中只有一个i变量。 当然获取的都是一个值了。
    你要让每个添加进数组中的function都单独在一个闭包的作用域里面。每个作用域中都要有一个i变量function A() {
         var result = [];
         for (var i = 0; i < 3; i++)
             (function (i) {
                 result.push( function(){ console.log( "item " +i);});
             })(i);
         return result;
    }
    var a = A();
    for (var i = 0; i < 3; i++) {
        a[i]();
    }
      

  5.   

    或者把循环变量i改成let块作用域变量,块作用域也能产生闭包function A() {
         var result = [];
         for (let i = 0; i < 3; i++)
             result.push( function(){ console.log( "item " +i);});
         return result;
    }
    var a = A();
    for (var i = 0; i < 3; i++) {
        a[i]();
    }
      

  6.   

    那看一下效果, 当 result.push(function(){ console.log(1)} );   ,然后i变化 了,result.push(function(){ console.log(2)}) ;之前push的 function 的数值是 变化了一次咯?  还是这个是执行完了之后,一起push~
      

  7.   


    不是你想的这样的,运行期的时候方法执行的时候才会去寻找变量的值,所以前面那里push进去的function执行的时候去寻找i的值,这时候i已经是循环结束的结果了。而我上面说的那样方法执行的时候寻找i,i是当时传进去的那个i,可能这样写你会疑惑,换个变量名在理解下吧。
    function A() {
         var result = [];
         for (var i = 0; i < 3; i++)
             (function (reali) { // 形参
                 result.push( function(){ console.log( "item " +reali);}); // 所以这里始终是传进来的实参,所以得到正确的结果。这里运行的时候会去寻找reali变量,reali是外层作用域这个匿名函数传进来的i。
             })(i);// 实参
         return result;
    }
    var a = A();
    for (var i = 0; i < 3; i++) {
        a[i]();
    }
      

  8.   

    因为这个变量是一个空间内的固定的那个变量,这个值输出的时候肯定都是用那一个
    但是当这样写的时候
    for(i=0;i<3;i++)
    {
       function test(i)
       {console.log(i);}
       test(i);
    }
    这个操作里面  function  test里面的i和for里面的i是不在一个存储位置的,test函数声明时定义了形参i循环里的i作为参数传过去之后会在这个函数test所属的空间内重新生成一个i,这个i不会和循环那个i互相影响(除了参数的传递)。这个test所属的这块空间和空间里的变量也可以说就是个闭包。一般都用return把test这个函数运行结果return出去,这样就可以得到这个闭包的运行结果了。
      

  9.   

    也就是说  最开始 result.push 是一个function的地址引用吗?  然后当用到result的内容时候,找到这个function, function的值已经是执行完了的数值?  可以这么理解吗?  
    使用闭包的话, 实际上是不同的function的地址引用, 保存不同的数值。还是闭包每次开辟一个新的存储空间?之前的只有一个存储空间。  
      

  10.   

    js中可以在函数内部再定义函数(注意,是定义,不是调用)
    而定义函数时候会有一个作用域链,作用域链会保存局部变量
    因此你可以参考相关资料就可以解释为何会访问最后一个值
    (因为定义后,作用域链三层次,最外层全局,第二层包含for循环中的值,第三层才是你定义的函数)
    也欢迎去看看我的博客~~