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
答案 0 :(得分:5)
你不希望secrets
达到你所拥有的级别。作为Bergi said,它是内存泄漏。
(注意:当我说&#34;真正私密&#34;下面,请记住,如果有人使用调试器,那么<strong>没有是真正私密的。&#34;真正的私人&#34;以下只是让任何人都无法编写代码,使用对象的引用来获取或修改私有数据。)
ES7将拥有真正的私有财产。在那之前,你基本上有三个选择:
通过对构造函数调用的闭包来保存真正的私有数据
&#34;保持双手&#34;属性通过属性命名约定
非常难以使用的属性,虽然不是私有的,但很难编写代码
如果您希望基于每个实例获得真正的私有信息,那么标准的方法是使用构造函数中的变量,并定义构造函数中需要私有数据的方法:
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; 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)