JS for循环 闭包

对于for循环的闭包问题的理解,认为需要理解函数中的变量的作用域链的概念 另外提及下变量提升的概念

如下例子:

var ar = [];
for(var i=1;i<10; i++){
  ar[i] = function(){
    console.log(i);
  }
}

ar[5]       // 打印为10;因为有闭包函数的问题

理解好闭包,应该理解好函数中变量的作用域概念。

首先,函数是有自己的执行环境(context)概念,函数的变量,就有变量作用域链。函数中,可以声明自己的局部变量,函数外是访问不到的。函数同样可以利用函数外声明的变量,但是此变量不属于函数。函数中变量的利用,存在一个在执行环境的变量作用域链查找的问题,若在函数内找不到声明,就到函数外找,如下图

(注:此图为转用,非本人制作)
因此就能很好的解释为啥上述例子结果是10的问题,因为子function利用的i,i在子function没有局部定义,function并不是立即执行,所以这里的i一直是外部i的内存引用,所以当function执行时按照变量作用域链的方式查找,当找到变量的时候,for循环早已经执行完,于是结果为10。

上面的话通过函数执行的理解是:在函数执行时,会创建一个新的Activation Object对象,这个对象中包含了this、参数(arguments)、局部变量(包括命名的参数)的定义,这个Activation Object对象会被置于作用域链的最前面。 
所以在Scope Chain中最后顺序是本函数的Activation Object,然后是上层函数的Activation Object,再上上层的Activation Object,一直到Global Object。函数执行时需要的变量,如果AO没有的话,就按照作用域链往上找,于是就找到此时已经变为10的i。理解AO 与 作用域链是理解的关键。同时能够很好的理解ES 6 的let 定义变量为啥能避开闭包的问题的原理了。

通过函数的形式,产生了闭包。可通过传递参数,函数立即执行的方式,解决闭包。另外,还可通过let定义变量的方式 for(let i=0; i<10; i++){}。

 对于变量的声明提升的概念就是,只要在

    function(){
      alert(i);
      var i=9 ;

    }
  实际是这样的
    function(){
        var i;
        alert(i);
        i = 9;
    };

posted @ 2016-12-13 12:07  a fine day  阅读(774)  评论(0编辑  收藏  举报