You don't want secrets at the level you have it. As Bergi said, it's a memory leak.
(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. 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
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.
"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 _. 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.
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):
First, you create a 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.
secret[this.id].events = events || 0;you wantsecret[this.id].events = events || {};.eventsis used as if it was an object, but seems to be a number.secretobjects pose a severe memory leak… I would advise against using such a pattern.secret[this.event2index[eventName]]where secret is an array and event2index an object that gives each eventName a specific index in the array? Edit: actually nvm.