Javascript Module pattern with private/public methods

时间:2015-06-30 13:57:42

标签: javascript jquery

I'm asked to make a Javascript Module that acts as counter of browser events and is not possible to modify the actual counted events (Private method).

var CountingLogger = (function() {

var secret ={};
var uid = 0;
function CountingLogger(events) {
    secret[this.id = uid++] = {};
    // Store private stuff in the secret container
    // instead of on `this`.
    secret[this.id].events = events || 0;
}

CountingLogger.prototype.log = function (eventName) {
    alert(secret[this.id].events[eventName]);
    if (typeof secret[this.id].events[eventName] === 'undefined') {
        secret[this.id].events[eventName] = 0;
    }
    secret[this.id].events[eventName]++;
    var count = secret[this.id].events[eventName];
    $('#logContents').append('<li>' + eventName + ': ' +  count + '</li>');
};

return CountingLogger;
}());

in the main.js I define: var logger = new CountingLogger(); then call logger.log('EventName');

And should appear as callback a counter "EventName" + Counter, so Eventname: 1, SecondEvent: 4... But in the log always shows 'WhateverEvent' undefined. Can anybody please have an idea how this can be solved? Regards

2 个答案:

答案 0 :(得分:5)

你不希望secrets达到你所拥有的级别。作为Bergi said,它是内存泄漏。

(注意:当我说&#34;真正私密&#34;下面,请记住,如果有人使用调试器,那么<​​strong>没有是真正私密的。&#34;真正的私人&#34;以下只是让任何人都无法编写代码,使用对象的引用来获取或修改私有数据。)

ES7将拥有真正的私有财产。在那之前,你基本上有三个选择:

  1. 通过对构造函数调用的闭包来保存真正的私有数据

  2. &#34;保持双手&#34;属性通过属性命名约定

  3. 非常难以使用的属性,虽然不是私有的,但很难编写代码

  4. 真正的私人数据

    如果您希望基于每个实例获得真正的私有信息,那么标准的方法是使用构造函数中的变量,并定义构造函数中需要私有数据的方法:

    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引擎可以在这些函数对象中重用函数的代码

    &#34;保持双手&#34;属性

    但大多数情况下,您不需要真正的私人信息,只需要提供信息,然后保持双手离开我。&#34; JavaScript中的约定是以_开头的属性。是的,这意味着可以访问实例的代码可以使用或更改该属性的值,但在大多数具有&#34;真正私有&#34;的语言中,这实际上是正确的。属性,例如Java,通过反射。

    非常难以使用的属性

    如果你想让那些试图使用你的私人数据的人生活更加艰难,你可以使用an old blog article of mine *中的这个技巧(当ES6通过Name获得真正的隐私时,它被写回来了对象;从那时起,Name已变为Symbol,并且它不再用于隐私了):

    首先,您创建一个Name伪类:

    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
    

    现在,每次代码运行时,私有属性的名称都不同。

    这仍然不是私人。它更难找到。

答案 1 :(得分:0)

javascript中的私有方法只能用于encapsulation目的。

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

用户只需在私有方法上放置一个调试点,然后开始操纵您的私有逻辑。