美文网首页
review javascript 25:闭包

review javascript 25:闭包

作者: 蝴蝶结199007 | 来源:发表于2017-05-30 23:15 被阅读8次

    (1)知识点

    • (1.1)定义
    • (1.2)变量的作用域
    • (1.3)如何从外部读取局部变量
    • (1.4)判断闭包
    • (1.5)用途
    • (1.6)使用注意点
    • (1.7)面试题

    (2)细化

    (2.1)定义

    能够读取其他函数内部变量的函数称之为闭包。

    (2.2)变量的作用域

    要理解闭包,首先要先理解闭包的作用域:全局变量和局部变量
    全局变量:即定义在函数外部的变量
    优:反复使用,且共享使用
    缺:可能随时在任意位置被篡改——全局污染
    局部变量:使用var声明,定义在函数内部的变量
    不可反复使用!方法调用完自动释放

    函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
    Tips:尽量避免使用全局变量

    (2.3)如何从外部读取局部变量

    使用闭包,即在函数内部再定义一个函数

      function f1(){
        var n=999;
        function f2(){
          alert(n); // 999
        }
      }
    

    函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的;但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。

    这个时候只需要将f2作为返回值,那么在外部就可以读取到f1中的变量n了

       function f1(){
        var n=999;
        function f2(){
          alert(n); 
        }
        return f2;
      }
      var result=f1();
      result(); // 999
    

    由此,f2函数即形成了闭包。

    (2.4)判断闭包

    a. 内外层函数嵌套
    b. 内层函数必须使用了外层函数的局部变量
    c. 外层函数将内层函数返回到外部,可在外部调用
    Tips:外层函数调用了几次,就有几个受保护的局部变量副本

    (2.5)闭包的作用

    a. 可以读取函数内部的变量
    b. 使得这些变量的值始终保持在内存中,不会在调用结束后,被垃圾回收机制回收

      function f1(){
        var n=999;
        nAdd=function(){n+=1}  //匿名函数
        function f2(){
          alert(n);
        }
        return f2;
      }
      var result=f1();
      result(); // 999
      nAdd();
      result(); // 1000
    

    result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

    (2.6)使用注意点

    a. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除
    b. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    (2.7)面试题

        function outer(){
          for(var i=0,arr=[];i<3;i++){//i受保护的变量
            arr[i]=function(){return i};
          }//i变成了3
          return arr;
        }
        var funs=outer(); //外层函数调用一次,只有1个i
        console.log(funs[0]()); //3
        console.log(funs[1]()); //3
        console.log(funs[2]()); //3
    

    (3)实践

    <script type="text/javascript">
        /*定义一个函数,模拟取号机:
         每次取一个数
         数是连续不重复的
         */
        //定义工厂函数保护局部变量
        function factory(){
            var n=0;//受保护的局部变量
            return function(){ return ++n; }
        }
        //获得返回的内部函数对象
        var ccb=factory();//外层函数调用第一次
        //ccb:function(){ return ++n; }
        //使用内部函数对象操作受保护的变量
        console.log(ccb());//1
        console.log(ccb());//2
        n=1;
        console.log(ccb());//3
        console.log("----------");
    
        var icbc=factory();//外层函数调用第二次
        console.log(icbc());//1
        console.log(icbc());//2
        console.log("----------");
    </script>
    

    参考学习:
    学习Javascript闭包 ---- 阮一峰

    相关文章

      网友评论

          本文标题:review javascript 25:闭包

          本文链接:https://www.haomeiwen.com/subject/uefdfxtx.html