• JavaScript闭包


    一些常见的闭包题目:

    1.

    
    
    //1秒后同时输出5个5,运用每次运用i后都自动销毁,最后一次i=5,放到每次函数里面执行;
     for (var i = 0i < 5i++) {
       setTimeout(function() {     
        console.log(i);
       }, 1000); //若为1000*i,开始输出一个 5,然后每隔一秒再输出一个5,一共5个5
     }

    2.

    
    
    //要想1秒后,同时输出0到4,解决办法一般有两个:
    //1,setTimeout函数外面加一层闭包,闭包后变量立即执行。
     (function(i) {
       setTimeout跑这里
     })(i);

    //2,把var改为let

    3.

    
    
    //在循环体函数里面加一层
    (function() {
        想要运行的函数
      })(i);
    //其实这层是没效果的

    4.使用return的情况

    
    
    //1秒后同时输出5个5:
      for (var i = 0i < 5i++) {
       setTimeout(function() { //这里传进参数i,就可以使1秒后,同时输出0到4
         return function() {
           console.log(i);
         }
       }(i), 1000); //若为1000*i,则开始时输出一个5,然后每隔一秒再输出一个,一共5个5
     }

    5.console.log后面绑定i参数

    
    
    //马上输出0到4,只要console.log后面绑定i参数,永远是立刻输出0到4
     for (var i = 0i < 5i++) {
       setTimeout(function(i) {//有没有参数i都没影响
         console.log(i);
       }(i),1000); //无论这个是1000*i还是多少,都无效
     }

    6.promise的执行顺序

    
    
    //立刻输出2,3,5,4,1
       setTimeout(function() {
           console.log(1)
         }, 0);
       new Promise(function executor(resolve) {
         console.log(2);
         forvar i=0 ; i<10000 ; i++ ) {
           i == 9999 && resolve();
         }
         console.log(3);
       })
       .then(function() {
         console.log(4);
       });
       console.log(5);

    7.深入地理解闭包

    
    
     function f1(){
          var n=999;
          function f2(){
            alert(n);
          }
          return f2;
        }
        var result=f1(); //如果直接运行f1()是无效的,必须把return值保存到变量中。
        result(); // 999
    //f2可以读取f1中的局部变量,那么只要把f2作为返回值,就可以在f1外部读取它的内部变量了

     闭包就是能够读取其他函数内部变量的函数。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中:

    
    
      function f1(){
        var n=999;
        nAdd=function(){  //全局变量,匿名函数
                n+=1;
            }
        function f2(){
          console.log(n);
        }
        return f2;
      }
      var result=f1();
      result(); // 999
      nAdd();
      result(); // 1000

    //这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
    //f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制回

    8.闭包的弊端:

    1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    
    
    function assignHandler(){
        var element=document.getElementById('someElementId');
        element.onclick=function(){ //闭包
            alert(element.id);  //调用了element,它会一直存在于内存中,不会被垃圾回收机制回收掉,所以导致了内存泄漏
        }
    }

    解决办法:尽量引用包含函数的值类型变量,不引用包含函数的引用类型变量,且必须在包含函数的最后将引用变量的值设置为null,断开变量名与对象之间的连接,这样对象便可正常回收。

    
    
    function assignHandler(){
        var element=document.getElementById('someElementId');
        var id=element.id;
        element.onclick=function(){
            alert(id);
        }
        element=null;
    }

    9.几个例子理解:

    
    
    function Foo() {
        var i = 0;
        return function() {
            console.log(i++);
        }
    }
     
    var f1 = Foo(),
        f2 = Foo();
    f1();//0
    f1();//1
    f2();//0 与f1是不同的

     

    
    
      var val1=0;
      var val2=0;
      var val3=0;
      for(var i1=1;i1<=3;i1++){ //i1最终为4
          console.log('i1='+i1);
          var i2=i1;            //i2最终为3
          console.log('外面i2='+i2);
          (function(){
              console.log('里面的i2='+i2);
              var i3=i2;       //i3只存在闭包里,不被销毁
              console.log('i3='+i3);  //执行到这里后回到上面的i1,循环,直到i1条件不满足
              setTimeout(function(){ //1秒后,连续执行3次里面的函数
                console.log(i1);//4,4,4
                console.log(i2);//3,3,3
                console.log(i3);//1,2,3
                 val1+=i1;
                 val2+=i2;
                 val3+=i3;
             },1);
        })();
     }
     
     setTimeout(function(){
         console.log(val1); //12
         console.log(val2); //9
         console.log(val3); //6
     },100)

     

  • 相关阅读:
    进程 线程
    random模块 时间模块 sys模块 os模块 json模块 pickle模块
    异常处理
    面向对象进阶篇
    面向对象初级篇
    正则表达式
    re模块的相关知识
    CNN归纳偏好
    window和Linux下安装nvidia的apex
    使用GrabCut做分割
  • 原文地址:https://www.cnblogs.com/shen076/p/6555718.html
Copyright © 2020-2023  润新知