When you get into a bit higher end JavaScript patterns, one thing you’ll read very early on is this concept: that although JavaScript does not have private members or access modifiers, it is possible to achieve this behavior with closures. This is often done through an IIFE and is the simplest implementation of the module pattern. Like so:
[php lang=“JavaScript”]var mod = (function() {
var privateVar = “foo”;
return {
getPrivateVar: function() {
return privateVar;
},
setPrivateVar: function(value) {
privateVar = value;
}
};
}());
console.log(mod.getPrivateVar());
mod.setPrivateVar(“buzz”);
console.log(mod.getPrivateVar());[/php]
The IIFE executes, returning an object with a couple of methods. These methods have access to the original privateVar, which is not accessible anywhere else. Private var, right? All good and well, but I’ve noticed one aspect of this that almost nobody ever talks about…
Modules are singletons.
OK, they are not really singletons in the full sense of the singleton pattern with a static getInstance method and a guard against creating multiple instances. But they are objects that are created a single time and unless you were to copy and paste the code that creates them, there’s no real way to create an additional instance of one of them.
I’m not going off into a “singletons are evil” rant or anything, but it should be pointed out that modules created in this way only have a single instance. This is pretty obvious, since the module is created by an IIFE, which runs once when it is defined, and that’s it. For most things that you would define as “modules” this is probably exactly what you want, which I guess is why nobody talks about it. A module is often a library, like underscore or jquery, etc. Something you generally would not want multiple copies of floating around in the first place.
But say you want some kind of object that it would make sense to have multiple copies of. Say a game with players. If you defined a player object like above, you could only have a single player. So you need to change things somehow to allow for multiple instances.
The first idea is just to remove the IIFE and just have a function that you can call multiple times to create individual objects:
[php lang=“JavaScript”]function playerMaker(pname) {
var name = pname;
return {
getName: function() {
return name;
},
setName: function(value) {
name = value;
}
};
}
var player1 = playerMaker(“Fred”);
console.log(player1.getName());
var player2 = playerMaker(“Barney”);
console.log(player2.getName());[/php]
This works just fine, but do you see the issue here? that return object is created anew every single time you create a new instance. Not a big deal in a trivial example like this, but say you had an object with dozens of properties and methods and you were creating scores of these things. All those methods and properties would be created as brand new methods and properties on every object, cranking up your memory consumption and creation time. Probably not a good idea in most cases.
We could then turn to something like the revealing module pattern, which defines the functions a single time in the module, and then returns an object that references these. In this case, we still want playerMaker to be a function, so we return a function that returns an object that references the single instances of the methods:
[php lang=“JavaScript”]var playerMaker = (function() {
var name = “”;
function getName() {
return name;
}
function setName(value) {
name = value;
}
return function() {
return {
getName: getName,
setName: setName
};
};
}());
var player1 = playerMaker();
player1.setName(“Fred”);
var player2 = playerMaker();
player2.setName(“Barney”);
console.log(player1.getName());
console.log(player2.getName());[/php]
Only this doesn’t work at all, because the “private” var name is defined only once in the original IIFE and is like a static var amongst all instances. If you tried to move it into the return function at line 12, it wouldn’t work, because then it would not be in the scope that the getName and setName functions would have access to.
The long and the short of it is that for private properties to work, they rely on a closure, and for multiple instances to each have their own accessors and private properties, each one needs to have its own closures. A shared closure can only access a shared property. So we can’t really escape the second example.
Perhaps there is some way to do this, but I suspect that the complexity involved would probably outweigh the benefits.
In my original draft of this post, I went into a minor rant about how you shouldn’t worry about private vars in JavaScript, as it doesn’t have them and it doesn’t make sense to over-engineer all kinds of complexity to simulate them. But I’m not feeling very ranty at the moment, so I deleted all that.
This isn’t to say that the module pattern as commonly used, with its private vars and methods is bad. It’s actually quite simple and elegant as long as you only need a single instance of that module, and I back it up as a great pattern 100%. But if you are trying to extend it to objects with multiple instances, I think you are best to leave privacy behind.
Interestingly, between the time of writing this post and publishing it (a couple of days) I listened to the latest JavaScript Jabber podcast http://javascriptjabber.com/005-jsj-javascript-objects/ on “JavaScript Objects”. A great listen, and some of these very points were brought up. Check that one out. It’s a great new podcast as a whole, and with only 5 episodes so far, well worth going back to the start and checking out all of them.