• for循环添加的闭包问题


    function test(){
      var arr = [];
       for (var i=0;i<10;i++){
          arr[i] = function(){
           console.log(i);   
         }  
       }
       return arr;
    }
    var myArr = test();
    
    for (var i=0;i<myArr.length;i++){
      myArr[i]();  //结果为10个10
    }

    结果分析:

    这是一个典型的闭包问题:

    特点:arr[i] = function(){ console.log(i);  } 中保存了i的引用,当myArr[i]()执行时,就要去寻找引用的上下文中的i

    顺序:

    函数提升和变量提升

    1、GO

    myArr:undefined;

    test:function test(){};

    i:0

    2、test()执行

    生成[[scope]]对象 

    [0]:test.AO{arr:[],i:10;}

    注意:arr[i]和函数内的i是没有关系的;

    [1]:GO

    3、myArr[i]()执行的时候,test()已经执行完毕,会删除对执行上下文的引用,但是myArr[i]()没有删除对执行上下文的应用,还有每一次重新调用函数会重新生成一个执行上下文,和以前的执行上下文没有关系;

    所以myArr[i]的所有的函数都指向一个执行上下文,也就指向同一个i;当test()执行完毕以后,i就已经变为10;所以当i=10 即10<10,条件不满足,所以停止;输出9个10

    4、这个问题主要是执行上下文[[scope]]的AO和GO

    解决办法:

    function test(){
      var arr = [];
       for (var i=0;i<10;i++){
          (function(j){
             arr[j]=function(){
                 console.log(j);
               }
         }(i))
       }
       return arr;
    }
    var myArr = test();
    
    for (var i=0;i<myArr.length;i++){
      myArr[i]();  //结果为10个10
    }    

    用闭包解决闭包问题

    上一个问题,在于生成的10个函数同时指向同一个执行上下文,所以i会的值是统一的,当test()执行完毕i=10,并且断开对函数的AO的引用,但是闭包函数还在引用同一个AO所以i都等于10

    解决办法是:

    把每一个函数的指向的执行上下文单独独立开,10个函数有10个执行上下文,不指向同一个;

    而且使用了立即执行函数,所以把i传给j,建立新的指向AO,每一次执行完函数销毁,会创建一个新的立即执行函数,所以指向的AO的上下文是不一样,不会受到影响

  • 相关阅读:
    「模板」 树套树
    [Luogu 3701] 「伪模板」主席树
    「模板」 可持久化平衡树
    「模板」 割点
    [Luogu 2596] ZJOI2006 书架
    省选有感。(不是游记)
    [Luogu 2604] ZJOI2010 网络扩容
    MySql聚簇索引与非聚簇索引的区别
    四层负载均衡和七层负载均衡的区别
    Redis利用Pipeline加速查询速度的方法
  • 原文地址:https://www.cnblogs.com/jokes/p/9203856.html
Copyright © 2020-2023  润新知