Sep 24 2009
Singletons in JavaScript
I use singletons all over the PirateQuesting code, but I’ve never explained the idea here, nor how they are different from singletons in other languages.
Anyone familiar with common design patterns knows how singletons work in the vast majority of languages. For a PHP example, see this post.
In JavaScript there are basically two main ways to create a singleton. One is use immediate instantiation so that the class may not be instantiated again. The second is closer to the traditional singleton pattern, however, since there are no private members or constructors, we can get around this by using a nested ‘class’ constructor — and there are two ways to accomplish this.
The first way is done as follows:
var singleton = new (function Singleton() {
this.value = 12;
} )();
alert(singleton.value); // alerts 12;
var singly = new Singleton(); // Singleton is not defined.
alert(singleton instanceof Singleton); // Singleton is not defined
In the above, the constructor name, Singleton, isn’t really necessary. While it can’t be used to instantiate the Singleton again, it also can’t be used with instanceof or typeof so feel free to leave it out if you want; leaving it in, does make it more obvious what is happening though.
And the second way (version 1):
var Singleton = (function () {
var instance = null;
function Singleton() {
this.value = 12;
}
this.getInstance = function () {
if (instance === null) {
instance = new Singleton();
}
return instance;
}
})();
var singleton = Singleton.getInstance();
alert(singleton.value); // alerts 12;
var singly = new Singleton(); // Singleton is not a construct
alert(singleton instanceof Singleton); //invalid 'instanceof' operand Singleton
The above is just an anonymous function being called immediately (note the () after the function declaration). Inside the function it declares a pseudo-private member called instance, a pseudo-private constructor, Singleton, and a getInstance method. The getInstance method can see instance due to closure, while the outside world has no idea that it exists.
And finally, the second way (version 2):
var Singleton = {
getInstance : (function() {
var instance;
function Singleton() {
this.value = 12;
}
return function () {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
})()
}
var singleton = Singleton.getInstance();
alert(singleton.value);
var singly = new Singleton(); // Singleton is not a constructor
alert(singleton instanceof Singleton); //invalid 'instanceof' operand Singleton
In this final example, all of the logic is put into the getInstance function which is the result of a self-calling function which itself returns a function. Yeah, it’s a little hard to follow, but basically the returned function has visibility of instance and the Singleton constructor due to closure.
As a closing note, it’s worth pointing out that although all of the above methods do not permit a second instance construction, they also do not allow use of typeof or instanceof for type verification.
Update
Based on a comment below by Peter Robinett, I’ve come up with a different way to do this, which allows for instanceof and typeof and seems to be an all-round good solution to the problem. It does not, however use the classical getInstance method, but works well all the same.
var Singleton = function () {
var instantiated = false;
return function () {
if (instantiated) {
throw "Singleton already instantiated";
}
instantiated = true;
this.value=12;
}
}()
var singleton = new Singleton();
alert(singleton.value); //alerts 12
alert(singleton instanceof Singleton); alerts true
var singly = new Singelton(); //throws exception and cannot be instantiated

December 5th, 2009 at 9:35 am
Hi Jonathan,
Is there a way to avoid those invalid instanceof operand errors? I’ve got some code I can’t easily change and would like to be able to use instanceof.
Thanks,
Peter Robinett
December 5th, 2009 at 2:45 pm
@peter
I really wish there were. The problem is this: You can’t make an object un-instantiable as there are no private constructors — just prototypes. You can control scope somewhat, and that’s what I’ve done above. By nesting your constructor inside another function, the global scope doesn’t have visibility of the constructor. And if scripts can’t see it, then they can’t instantiate it. However, if scripts can’t see it, then they also can’t verify what it is — hence why instanceof fails.
The one option that might work is to create a constructor function that throws an exception if it has already been instantiated before. In fact, I’ll add that to the post above.