简体   繁体   English

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

[英]Javascript Module pattern with private/public methods

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). 我被要求制作一个Javascript模块来充当浏览器事件的计数器,并且无法修改实际的计数事件(私有方法)。

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(); 在main.js中,我定义了: var logger = new CountingLogger(); then call logger.log('EventName'); 然后调用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. 并且应在回调中显示一个计数器“ EventName” + Counter,因此事件名称:1,SecondEvent:4 ...但在日志中始终显示未定义的“ WhateverEvent”。 Can anybody please have an idea how this can be solved? 任何人都可以知道如何解决吗? Regards 问候

You don't want secrets at the level you have it. 您不希望拥有自己级别的secrets As Bergi said , it's a memory leak. 正如Bergi所说 ,这是内存泄漏。

(Note: When I say "truly private" below, remember that nothing is truly private if someone's using a debugger. "Truly private" below just makes it's impossible for anyone to write code that, using a reference to the object, gets or modifies the private data.) (注意:当我在下面说“真正私有”时,请记住,如果有人正在使用调试器,则没有什么是真正私有的。下面的“真正私有”只是使任何人都不可能编写使用对该对象的引用来获取或修改的代码。私人数据。)

ES7 will have truly private properties. ES7将拥有真正的私有财产。 Until then, you basically have three options: 在此之前,您基本上有三个选择:

  1. Truly private data, held via closures over the call to the constructor 真正的私有数据,通过对构造函数的调用的闭包来保存

  2. "Keep your hands off" properties via a property naming convention 通过属性命名约定“保持双手”属性

  3. Very-hard-to-use properties that, while not private, are very hard to write code against 很难使用的属性,虽然不是私有的,但很难根据它们编写代码

Truly Private Data 真正的私人数据

If you want truly private information on a per-instance basis, the standard way to do that is using variables in the constructor , and define methods that need that private data within the constructor: 如果您希望按实例获取真正的私有信息,那么标准的方法是在构造函数中使用变量,并在构造函数中定义需要该私有数据的方法:

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");
};

Yes, that means a new iWillTellYouASecret function is created for every instance, but it (and the secret) are also reclaimed when that instance is removed from memory, and a decent JavaScript engine can reuse the function's code across those function objects. 是的,这意味着将为每个实例创建一个新的iWillTellYouASecret函数,但是当将该实例从内存中删除时,该函数(和秘密)也会被回收 ,并且不错的JavaScript引擎可以在这些函数对象之间重用该函数的代码

"Keep your hands off" Properties “放开手”属性

But most of the time, you don't need truly private information, just information saying "keep your hands off me." 但是在大多数情况下,您不需要真正的私人信息,只需说“让我远离您”的信息。 The convention for that in JavaScript is properties beginning with an _ . JavaScript中的约定是以_开头的属性。 Yes, that means that code with access to instances can use or change that property's value, but that's actually true in most languages that have "truly private" properties as well, such as Java, via reflection. 是的,这意味着可以访问实例的代码可以使用或更改该属性的值,但是在大多数具有“真正私有”属性的语言(例如Java)中,通过反射实际上也是如此。

Very-Hard-to-Use Properties 很难使用的属性

If you want to make life harder on people trying to use your private data, you can use this trick from an old blog article of mine *(it was written back when ES6 was going to have true privacy via Name objects; since then, Name has turned into Symbol and it isn't used for privacy anymore): 如果您想让试图使用您的私人数据的人生活变得更艰难,可以使用我的一篇旧博客文章中的技巧*(当ES6通过Name对象具有真正的隐私时便写回了该Name ;从那时起, Name已经变成了Symbol ,并且不再用于隐私):

First, you create a Name psuedo-class: 首先,创建一个Name psuedo-class:

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;
}();

Then you use this pattern for your private instance properties: 然后,将此模式用于私有实例属性:

// 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

Now, the name of your private property is different every time your code runs. 现在,每次运行代码时,私有财产的名称都会不同。

This still isn't private . 这仍然不是私人的 It's just harder to find. 很难找到。

Private methods in javascript should only be used for encapsulation purposes. javascript中的私有方法只能用于封装目的。

It's impossible to prevent someone from manipulating any method in javascript. 不可能阻止某人操纵javascript中的任何方法。

A user can simply place a debug point on your private method and start to manipulate your private logic. 用户可以简单地在您的私有方法上放置一个调试点,然后开始操纵您的私有逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有私有/公共方法的高效Javascript模块模式 - Efficient Javascript Module pattern with private/public methods 使用JavaScript模块模式时,应将私有方法放在哪里? - Where should private methods be placed when using the JavaScript Module pattern? 揭示模块模式(javascript) - 这不能访问私有方法 - revealing module pattern (javascript) - this cannot access private methods JavaScript中的私有和公共方法以及变量 - Private and public methods and variable in JavaScript JavaScript模块模式:私有方法如何访问模块的范围? - JavaScript module pattern: How do private methods access module's scope? 如何在JavaScript模块模式中的私有函数中调用公共函数 - How do I call a public function from within a private function in the JavaScript Module Pattern 在使用javascript模块模式时,如何从私有方法中调用公共方法? - How can i call a public method from within a private one when using the javascript Module Pattern? 公共方法访问Javascript中的私有成员 - Public methods accessing private members in Javascript javascript模式:在私有和公共函数中引用“ this” - javascript pattern : referencing “this” inside private and public functions 向JavaScript模块模式添加方法 - Adding methods to JavaScript module pattern
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM