Rumah  >  Soal Jawab  >  teks badan

javascript 闭包是如何处理父函数中 let 形成的块级作用域中的变量呢?

function test(){
  var arr = [];
  for(var i = 0;i < 10;i++){
    arr[i] = function(){
      return i;
    };
  }
  for(var a = 0;a < 10;a++){
    console.log(arr[a]());
  }
}
test(); // 连续打印 10 个 10

为什么把上面第三行代码的 var i = 0 改为 let i = 0 后,调用 test() ,就会打印 1到9 了呢?

javascript 闭包是如何处理父函数中 let 形成的块级作用域中的变量呢?

天蓬老师天蓬老师2771 hari yang lalu408

membalas semua(3)saya akan balas

  • 天蓬老师

    天蓬老师2017-04-11 12:45:23

    当你用var的时候,如下:

    
    函数1作用域
    for(var i = 0; i < 10; i++) { 函数1作用域
            我在函数1作用域中
            arr[i] = function() { 函数2作用域
              我在函数2作用域中
              return i;
            };
    }
    函数1作用域
    console.log(i); 毫无疑问,执行到这里的时候,i是10,既然这里是10
                    那么在函数2作用域中访问i也是10也就不足为奇了
                    因为函数2作用域中没有,向上去函数1作用域中找
                    同一作用域中同一变量名的变量值肯定是相同的(未修改的情况下)
    

    --------------------------分界线-------------------------
    当你用let的时候,如下:

    块1作用域
    for(let i = 0; i < 10; i++) { 块2作用域
        我在块2作用域中
        console.log(i); // 毫无疑问,这里的i从0依次增加到10  
        arr[i] = function() { 块3作用域
          我在块3作用域中
          return i;
        };
    }
    块1作用域

    当你换成let的时候,读取i的时候,在当前作用域(块3)中没有找到,向上一个作用域(块2)寻找,在块2中发现i,于是拿到值。

    balas
    0
  • 大家讲道理

    大家讲道理2017-04-11 12:45:23

    http://stackoverflow.com/ques...

    balas
    0
  • 高洛峰

    高洛峰2017-04-11 12:45:23

     //1.执行完for之后,在for作用域中i的值为10 
    for(var i = 0;i < 10;i++){
        arr[i] = function(){
            return i;
        };
    }
    
    for(var a = 0;a < 10;a++){
    //2.程序执行for的时候访问闭包function(){return i}词法作用域向上查找,
    //  找到for(var i=0;i<10;i++)的词法作用域i=10,因此每次都是10
        console.log(arr[a]());
    }
    
    //假设上面的var i换成 let i的话
    for(let i=0;i<10;i++){
    //3 在这里每次循环的块作用域都被劫持了,并且每次迭代i都被重新声明
    //  即在此时,每层迭代会生成一个块作用域,并且变量i的值被定义为上次结算的值,
        arr[i] = function(){
            return i;
        };
    }
    
    for(var a = 0;a < 10;a++){
        //当再次访问闭包的时候访问的是劫持的块作用域,因此 i正确显示
        console.log(arr[a]());
    }
    

    let 关键字可以将变量绑定到所在任意作用域,即let为声明的变量隐式的劫持了所在的块作用域,将变量隐式附加在已经存在的块作用域中

    balas
    0
  • Batalbalas