带有私有/公共方法的Javascript模块模式

带有私有/公共方法的Javascript模块模式,javascript,jquery,Javascript,Jquery,我被要求制作一个Javascript模块,作为浏览器事件的计数器,并且不可能修改实际计数的事件(私有方法) var CountingLogger=(函数(){ var secret={}; var-uid=0; 函数计数记录器(事件){ secret[this.id=uid++]={}; //将私人物品存放在秘密容器中 //而不是“这个”。 secret[this.id].events=events | | 0; } CountingLogger.prototype.log=函数(eventNa

我被要求制作一个Javascript模块,作为浏览器事件的计数器,并且不可能修改实际计数的事件(私有方法)

var CountingLogger=(函数(){
var secret={};
var-uid=0;
函数计数记录器(事件){
secret[this.id=uid++]={};
//将私人物品存放在秘密容器中
//而不是“这个”。
secret[this.id].events=events | | 0;
}
CountingLogger.prototype.log=函数(eventName){
警报(机密[this.id].events[eventName]);
if(机密的类型[this.id].events[eventName]=“未定义”){
机密[this.id]。事件[eventName]=0;
}
secret[this.id].events[eventName]++;
var count=secret[this.id]。事件[eventName];
$(“#logContents”).append(“
  • ”+eventName+”:“+count+”
  • ”); }; 返回计数记录器; }());
    在main.js中,我定义:
    var logger=new CountingLogger()
    然后打电话
    
    logger.log('EventName')

    并且应该显示为回调计数器“EventName”+计数器,因此EventName:1,SecondEvent:4。。。 但日志中始终显示未定义的“WhateverEvent”。 谁能想出一个办法来解决这个问题?
    javascript中的私有方法只能用于特定目的。

    不可能阻止某人在javascript中操纵任何方法


    用户只需在您的私有方法上放置一个调试点,就可以开始操作您的私有逻辑。

    javascript中的私有方法应仅用于特定目的。

    不可能阻止某人在javascript中操纵任何方法


    用户只需在您的私有方法上放置一个调试点,就可以开始操作您的私有逻辑。

    您不需要您拥有的
    机密。因为,这是内存泄漏

    (注意:当我在下面说“真正私有”时,请记住,如果有人在使用调试器,没有任何东西是真正私有的。下面的“真正私有”只是让任何人都无法编写代码,使用对对象的引用来获取或修改私有数据。)

    ES7将拥有真正的私有财产。在此之前,您基本上有三种选择:

  • 真正私有的数据,在调用构造函数时通过闭包保存

  • 通过属性命名约定“请勿插手”属性

  • 非常难以使用的属性,虽然不是私有的,但很难针对这些属性编写代码

  • 真正私有的数据 如果您希望每个实例都有真正的私有信息,标准方法是在构造函数中使用变量,并在构造函数中定义需要该私有数据的方法:

    function Foo() {
        var secret = Math.floor(Math.random() * 100);
        this.iWillTellYouASecret = function() {
            console.log("The secret is " + secret);
        };
    }
    Foo.prototype.iDoNotKnowTheSecret = function() {
        console.log("I don't know the secret");
    };
    
    是的,这意味着会为每个实例创建一个新的
    iWillTellYouASecret
    函数,但当该实例从内存中删除时,它(以及秘密)也会被回收,一个体面的JavaScript引擎可以跨这些函数对象重用函数的代码

    “把手拿开”酒店 但大多数情况下,你并不需要真正的私人信息,只需要写着“把手从我身上拿开”的信息。JavaScript中的惯例是以
    \uuu
    开头的属性。是的,这意味着具有实例访问权限的代码可以使用或更改该属性的值,但在大多数具有“真正私有”属性的语言(如Java)中,这实际上也是通过反射实现的

    很难使用的属性 如果你想让试图使用你的私人数据的人生活更艰难,你可以使用*(这是在ES6将通过
    Name
    对象实现真正的隐私时写的;从那时起,
    Name
    变成了
    Symbol
    ,不再用于隐私):

    首先,创建一个
    Name
    psuedo类:

    var Name = function() {
        var used = {};
    
        function Name() {
            var length, str;
    
            do {
                length = 5 + Math.floor(Math.random() * 10);
                str = "_";
                while (length--) {
                    str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
                }
            }
            while (used[str]);
            used[str] = true;
            return new String(str); // Since this is called via `new`, we have to return an object to override the default
        }
    
        return Name;
    }();
    
    然后将此模式用于私有实例属性:

    // Nearly-private properties
    var Foo = (function() {
        // Create a random string as our private property key
        var nifty = new Name();
    
        // Our constructor    
        function Foo() {
            // We can just assign here as normal
            this[nifty] = 42;
        }
    
        // ***On ES5, make the property non-enumerable
        // (that's the default for properties created with
        // Object.defineProperty)
        if (Object.defineProperty) { // Only needed for ES3-compatibility
            Object.defineProperty(Foo.prototype, nifty, {
                writable: true
            });
        }
        // ***End change
    
        // Methods shared by all Foo instances
        Foo.prototype.method1 = function() {
            // This method has access to `nifty`, because it
            // closes over the private key
            console.log("Truly private nifty info: " + this[nifty]);
        };
        Foo.prototype.method2 = function() {
            // Also has access, for the same reason
            console.log("Truly private nifty info: " + this[nifty]);
        };
    
        return Foo;
    })();
    
    var f = new Foo();
    f.method1(); // Can use nifty!
    f.method2(); // Can too! :-)
    // Both `method1` and `method2` are *reused* by all `Foo` objects
    
    现在,每次代码运行时,私有属性的名称都是不同的


    这仍然不是私有的。它只是更难找到。

    你不想要你拥有的
    秘密。因为,这是内存泄漏

    (注意:当我在下面说“真正私有”时,请记住,如果有人在使用调试器,没有任何东西是真正私有的。下面的“真正私有”只是让任何人都无法编写代码,使用对对象的引用来获取或修改私有数据。)

    ES7将拥有真正的私有财产。在此之前,您基本上有三种选择:

  • 真正私有的数据,在调用构造函数时通过闭包保存

  • 通过属性命名约定“请勿插手”属性

  • 非常难以使用的属性,虽然不是私有的,但很难针对这些属性编写代码

  • 真正私有的数据 如果您希望每个实例都有真正的私有信息,标准方法是在构造函数中使用变量,并在构造函数中定义需要该私有数据的方法:

    function Foo() {
        var secret = Math.floor(Math.random() * 100);
        this.iWillTellYouASecret = function() {
            console.log("The secret is " + secret);
        };
    }
    Foo.prototype.iDoNotKnowTheSecret = function() {
        console.log("I don't know the secret");
    };
    
    是的,这意味着会为每个实例创建一个新的
    iWillTellYouASecret
    函数,但当该实例从内存中删除时,它(以及秘密)也会被回收,一个体面的JavaScript引擎可以跨这些函数对象重用函数的代码

    “把手拿开”酒店 但大多数情况下,你并不需要真正的私人信息,只需要写着“把手从我身上拿开”的信息。JavaScript中的惯例是以
    \uuu
    开头的属性。是的,这意味着具有实例访问权限的代码可以使用或更改该属性的值,但在大多数具有“真正私有”属性的语言(如Java)中,这实际上也是通过反射实现的

    很难使用的属性 如果你想让那些试图使用你的私人数据的人生活更艰难,你可以使用这个技巧