zoukankan      html  css  js  c++  java
  • 闭包_使用闭包

    许多编程语言使用私有变量,这些私有变量是对外部隐藏的对象属性。这是非常有用的一种特性,因为当通过其他代码访问这些代码时,我们不希望对象的实现细节对用户造成过度符合.遗憾的是,原生JavaScript不支持私有变量。
    但是,通过使用闭包,我们可以实现很接近的,可接受的私有变量,示例代码如下面例子所示。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../unitl/test.js"></script>
        <style>
            #results li.pass {color:green;}
            #results li.fail {color:red;}
        </style>
    
    
    </head>
    
    <body>
        <ul id="results"></ul>
    </body>
    <script>
    
        // 定义ninja构造函数。
        function Ninja() {
    
            //在构造函数内部声明一个变量,因为所声明的变量的所有域局限于构造函数的内部,所以它是一个“私有”变量。我们使用该变量统计ninja佯攻的次数。
            var feints = 0;
    
            //创建用于访问计数变量feints的方法。由于在构造函数外部的代码是无法访问feints变量的,这是通过办读形式访问该变量的常用方法。
            this.getFeints = function() {
    
                return feints;
            };
    
            //为feints变量声明一个累加方法。由于feints就私有变量在外部是无法累加的,累加过程则被限制在我们提供的方法中。
            this.feint = function() {
                feints++;
            };
    
    
    
        }
    
        // 现在开始测试,首先创建一个ninja的示例
        var ninja1 = new Ninja();
        //调用feint方法,通过该方法增加ninja的佯攻次数。
        ninja1.feint();
        
    
        //验证我们无法直接获取该变量值。
        assert(ninja1.feints === undefined,"Add the private data is inaccessible to us.");
        //虽然我们无法直接对feints变量赋值,但是仍然能够通过getFeints方法操作变量的值。
        assert(ninja1.getFeints()===1,"We are to access the internal feint count.");
    
    
    
        //当我们通过ninja构造函数创建一个新的ninja2实例时,ninja2对象则具有自己私有的feints变量。
        var ninja2 = new Ninja();
        assert(ninja2.getFeints() === 0, "the second ninja object gets its own feints variable.");
    
    </script>
    </html>
    

    我们创建了一个Ninja构造器。通过在函数上使用关键字new时,就会创建一个新的对象实例,此时调用构造函数,将新的对象作为它的上下文,所以,函数内的this将指向新的实例化对象。
    在构造器内部,我们定义了一个变量feints用于保存状态。由于javascript的作用域规则的限制,因此只能在构造内部访问该变量。为了让作用域外部的代码能够访问该变量,我们定义了访问该变量的方法getFeints。为了让作用域外部的代码能够访问私有变量,
    我们定义了访问该变量的方法getFeints。该方法可以读取私有变量,但不能改写私有变量。(只读访问的方法通常称为"getter")。

     function Ninja() {
                var feints = 0;
                this.getFeints = function() {
                      return feints;
                },
                this.feint = function() {
                      feints++;
                }
    
          }
    

    接下来创建增量方法feint,用于控制私有变量的值。在真实的应用程序中,该方法可能是一些业务逻辑的处理方法,但是在本例中,它只增加变量feints的值。
    在构造器完成了它的使命后,我们新建ninja1实例,并调用ninja1的实例方法feint:

          var ninja1 = new Ninja();
          ninja1.feint();
    

    通过测试显示,我们可通过闭包内部方法获取私有变量,但是不能直接访问私有变量。但有效地阻止了读私有变量不可控的修改,这与真实的面向对象语言的私有变量一样。这种情况如图
    所示。

    在构造器中隐藏变量,使其在外部作用域不可访问,但是可在闭包内部访问。

    • 通过变量ninja,对象实例是可见的。
    • 因为feint方法在闭包内部,因此可以访问feints。
    • 在闭包外部,我们无法访问变量feints。
      通过使用闭包,可以通过方法对ninja的状态进行维护,而不允许直接访问---这是因为闭包内部的变量可以通过闭包内的方法访问,构造器外部的代码则不能访问闭包内部的变量。
  • 相关阅读:
    tps,qps
    JS打包与代码分割
    css module
    垃圾回收算法、内存管理
    css flex布局
    angularJS transclude
    JS模块之AMD, CMD, CommonJS、UMD和ES6模块
    js event loop事件循环
    bootstrap3之栅格系统
    viewport理解
  • 原文地址:https://www.cnblogs.com/jamal/p/14173874.html
Copyright © 2011-2022 走看看