[英]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: 在此之前,您基本上有三个选择:
Truly private data, held via closures over the call to the constructor 真正的私有数据,通过对构造函数的调用的闭包来保存
"Keep your hands off" properties via a property naming convention 通过属性命名约定“保持双手”属性
Very-hard-to-use properties that, while not private, are very hard to write code against 很难使用的属性,虽然不是私有的,但很难根据它们编写代码
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引擎可以在这些函数对象之间重用该函数的代码 。
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)中,通过反射实际上也是如此。
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.