Click anywhere in the code to remove line numbers.
1 var singleton = new function() {
2 var rand = Math.round(Math.random() * 100);
3 this.getRand = function() {
4 return rand;
5 }
6 } In order to obtain a reference to the singleton instance, you'd just use the global variable singleton. Close, but no cigar. First of, look at this code:
Click anywhere in the code to remove line numbers.
1 var secondSingleton = new singleton.constructor;
2 document.write(singleton.getRand() + "\r\n");
3 document.write(secondSingleton.getRand()); Using the constructor attribute of the singleton object which holds a reference to the anonymous constructor function I can easily create a second instance of the "singleton". The code snippet above will therefore give you two different outputs, one for the original instance and one for the second instance. Two instances = no singleton. Of course circumventing the one-instance limitation required some "hacking" and therefore doesn't necessarily invalidate this solution. The real problem is that a singleton has a property that this solution doesn't take into account: an instance of a singleton is only created, when a special method (typically called getInstance) is invoked. The above solution will create an instance of the singleton regardless whether its actually needed or not. If the singleton allocates a lot of resources, executes a bunch of complex code or even does communication via Ajax in its constructor, then this behavior could be a problem.
In order to come up with a solution, I looked at how singletons are typically implemented in other languages like Java:
Click anywhere in the code to remove line numbers.
1 class Singleton {
2 private static Singleton instance = null;
3 private Singleton() { }
4 public static Singleton getInstance() {
5 if (instance == null) {
6 instance = new Singleton();
7 }
8 return instance;
9 }
10 } For singletons to work in JavaScript, I needed a way to do private constructors and both private and public static members, two concepts that JavaScript doesn't natively support. As ever so often, the solution was to use a closure to make the instance attribute and the constructor private. Here's the solution I came up with:
Click anywhere in the code to remove line numbers.
1 var Singleton = (function() {
2 var instance = null;
3
4 function PrivateConstructor() {
5 var rand = Math.round(Math.random() * 100);
6 this.getRand = function() {
7 return rand;
8 }
9 }
10
11 return new function() {
12 this.getInstance = function() {
13 if (instance == null) {
14 instance = new PrivateConstructor();
15 instance.constructor = null;
16 }
17 return instance;
18 }
19 }
20 })();
21
22 var singletonInstance = Singleton.getInstance(); The trick here is to define an anonymous function and call it immediately. The function creates a new variable scope in which we define a local variable "instance". The function then returns a new object that provides a privileged method "getInstance". Since this method holds a reference to the instance variable, a closure is formed and the local variable becomes a private static member. The actual constructor function is defined within the anonymous function and hence becomes inaccessible from the outside. Since getInstance also holds a reference to that function, another closure is formed allowing getInstance to create new instances using PrivateConstructor.
In a remotely aspect oriented kind of way, you could even do this:
Click anywhere in the code to remove line numbers.
1 var global = this;
2
3 function singletonify(constructorName) {
4 var constructorFunc = global[constructorName];
5 var instance = null;
6
7 global[constructorName] = new function() {
8 this.getInstance = function() {
9 if (instance == null) {
10 instance = new constructorFunc();
11 instance.constructor = null;
12 }
13 return instance;
14 }
15 }
16 }
17
18 function RegularConstructor() {
19 var rand = Math.round(Math.random() * 100);
20 this.getRand = function() {
21 return rand;
22 }
23 }
24
25 singletonify("RegularConstructor");
26
27 var myInstance = RegularConstructor.getInstance();
28 document.write(myInstance.getRand()); This will turn an existing constructor function into a singleton. The name of the constructor needs to be passed as a string to the singletonify function, because otherwise it wouldn't be able to overwrite the orignal constructor.
I hope someone find this useful. Please let me know what you think.

9 comments
Write a new comment | Trackback URI for this entryOne thing, though... the code you published above has a syntax error: the double-equal is missng from the line where you check if instance is null.
SHOULD readif (instance null) {or else it chokes.if (instance == null) {Other than that, kudos. I'm glad I found your site!
congratulations.
Do you sign autographs?
(A very minor thing: In the singletonify the "constuctorFunc" is misspelled - an "r" is missing)
i think the 2nd form is not really singleton since now anyone can new up a 2nd instance via the public constructor.
also note that line 4 in the java singleton patten, the getInstance() method should be synchronized.
thanks again!!
Can't you just use an (unnamed) object literal?
var singleton = { /* */ };
Just curious.
Yes, you could do that. But that won't give you a constructor or the ability to use closures to simulate private member variables and -functions. In some cases, an object literal will be just what you need and in other cases it won't suffice.
Write a new comment
<strong>,<em>,<cite>and<code>. Links, email addresses and line breaks are parsed automatically.