zoukankan      html  css  js  c++  java
  • Javascript进阶(5)---闭包

      维基:

      在计算机中,闭包(也称词法闭包或者函数闭包),是指一个函数或者函数的引用,与一个引用环境绑定在一起。这个引用环境是一个存储该函数每个非局部变量的表。

      百度百科:                                                          

        闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)

           


    1. 一个简单的例子 
      function outer(){
        var localVal = 30;
        return function(){
          return  localVal;
          }
        }
      var func = outer ();
      func();  //调用func()函数,得到30

      在outer()函数被调用之后,localVal未被释放,匿名函数执行的时候,仍能够调用外函数outer()中的localVal变量。(这就是一个简单的闭包)

    2. 闭包的优缺点
      • 优点:灵活方便、可进行封装
      • 不及时释放会造成是空间上的浪费、会造成内存泄漏、会造成性能上的消耗
    3. 其他例子
       1 function count(){
       2     var arr = [];
       3     for (var i = 1; i<=3; i++){
       4       arr.push(function(){
       5         return i*i;
       6       });
       7     }
       8   return arr;
       9   }
      10 var results = count();
      11 var res1=results[0];
      12 var res2=results[1];
      13 var res3=results[2];
      14 
      15 console.log(res1+"
      "+res2+"
      "+res3);
      16 /*function (){
      17         return i*i;
      18       }
      19 function (){
      20         return i*i;
      21       }
      22 function (){
      23         return i*i;
      24       }
      25 */
      • 注意在代码第4行中,push进数组的是匿名函数function函数体原封不动地放进了数组,变量 i 也没有进行取值运算
    console.log(res1()+"
    "+res2()+"
    "+res3());/*16  16  16 */
      •   因为在 “var results = count();” 执行之后,for 循环中的 i 值已经变为 4 ,现在调用,返回 i * i 的值自然是16
    • 如果想返回我们“原本期望的值“1 4 9”的话,我们尝试做出小的改动  
    • 1 function count(){
      2     var arr = [];
      3     for (var i = 1; i<=3; i++){
      4       arr.push(function(n){
      5         return function(){
      6            return n*n;
      7           }
      8         }(i));                //关键点在此处
      9     }
      10   return arr;
      11   }
      12 var results = count();
      13 var res1=results[0];
      14 var res2=results[1];
      15 var res3=results[2];
      16 
      17 console.log(res1+"
      "+res2+"
      "+res3);
      18 /*function (){
      19         return i*i;
      20       }
      21 function (){
      22         return i*i;
      23       }
      24 function (){
      25         return i*i;
      26       }
      27 */
      28 console.log(res1()+"
      "+res2()+"
      "+res3());/* 1 4 9*/
    • 我们再返回一个函数的同时使用“()”符号将函数就地执行了,这个要才能够保证内部函数中的 i * i 返回的是当次循环的的 i 值。

      4、其他笔记

    • 因为Javscript不算是一门面对现对象的语言,所以无法直接封装私有变量,但利用闭包,我们可以模拟这个过程
      1 function create_sth(initial){
      2     var x = initial || 0 ;
      3     return {
      4       inc : function (){
      5         x + = 1;
      6           return x;  //返回的对象中包含着inc函数,该函数又携带着一个局部变量x。
      7       }
      8     }
      9   }
    • 换句话说,闭包就是携带状态的函数,并且它的状态可以对外界完全隐藏起来。

       5、闭包的用处

    (function () {
      var userID = '我的ID';
      var someFunc = 'opening some function';
      var privateValue = 'var定义的内部privateValue';
      var publicValue = 'var定义的内部publicValue';
      //定义一个空壳对象,用于承载属性与方法
      var appObj = {};
      //定义一个私有方法,处理内部逻辑
      function usePrivateValue() {
        alert(privateValue)
      }
      //绑定一个公有方法,访问的是私有属性
      appObj.getUserID = function () {
        //do sth
        userID += ' 我被修改过了';
        return userID;
      }
      //绑定一个公有属性,将内部属性暴露出去
      appObj.publicVal = publicValue;
      //将创建的对象appObj通过赋值给window.application,挂在全局变量widnow上
      window.application = appObj;
    }()); //立即执行

    application.usePrivateValue(); //error application.usePrivateValue is not a function console.log(application.getUserID()); //我的ID 我被修改过了 console.log(application.publicVal); //var定义的内部publicValue console.log(application.privateValue); // undefined
    •  闭包不同于一般函数,它允许一个函数在立即此法调用的作用域外,仍可访问非本地变量。
    • 在例子中,有私有属性/方法,公共属性/方法,可以通过在公共方法中使用私有属性/方法将私有属性赋值给公有属性的方式,达到在其作用域之外,仍能够对其进行调用的效果。
    • 将所有的公共属性/方法都挂载到一个全局的属性application(可自定义)上,能够有效地区分,在全局使用var 直接声明的全局变量对这个闭包的影响
    • 这么做,也可以在一定程度上保障了闭包内部变量实现功能的稳定性,不易受外界变量影响

      

      

      

  • 相关阅读:
    txtbox取Calendar值
    【Spread Sheet 应用(一)】去掉原有功能键及添加功能键
    【SQLSERVER】存储过程基础
    【SQLSERVER】在存储过程中调用存储过程
    ASP.NET跨页面传值技巧(VB.NET篇)
    【EXCEL】IF...ELSE语句
    VB单元测试
    【VB.NET】窗体之间传值
    【Spread Sheet 应用(二)】常用属性设置
    【SQLSERCER】创建、改变、删除索引
  • 原文地址:https://www.cnblogs.com/HXW-from-DJTU/p/5936197.html
Copyright © 2011-2022 走看看