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的状态进行维护,而不允许直接访问---这是因为闭包内部的变量可以通过闭包内的方法访问,构造器外部的代码则不能访问闭包内部的变量。
  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/jamal/p/14173874.html
Copyright © 2011-2022 走看看