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.

18 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.
function singletonify(constructorName, constructorOwner)
{
constructorOwner = constructorOwner || global;
var constructorFunc = constructorOwner[constructorNam e];
var instance = null;
constructorOwner[constructorNam e] = new function()
{
//...
}
}
So now, we can call it something like:
Package1.PageController = function()
{
// Constructor
}
Package1.PageCon troller.prototype =
{
// Definition
run : function(){/*... */},
validate : function(el){/*... */},
}
singletonify(PageContro ller, Package1);
Package1.PageController.getIn stance().run();
Package1.PageC ontroller.getInstance().valida te("textbox1");
Package1.PageC ontroller.getInstance().valida te("textbox2");
Package1.PageC ontroller.getInstance().valida te("textbox3");
Also, why would one use this method rather than the one promoted by Douglas Crockford (http://yuiblog.com/blog/2007/0 6/12/module-pattern/), or is it really the same thing?
A little example would go a long way toward helping me (and maybe others) to wrap my head around this...I realize that extending this to a practical application is "an exercise that is left to the reader", but I'd really appreciate it if you could extend this writeup to hold my hand a bit with a fuller example of how to use it.
Thanks.
As far as I know, everything you normally put in a JS object goes in the privateConstructor function.
Look in the example code in the blog post for a function "getRand". This is a public member function.
What I wanna say is that in javascript you don't need Singleton at all - the pattern is designed for languages which are restricted by the "class" statement. Javascript is not. In JS the classes are as dynamic as their objects, in fact they are objects themselves. The simple and standard solution is creating the functional object, which you can refer to as "static class":
my.somepackage.SomeCla ss =
{
property1: function(){},
method1: function(){
// to reference properties instead of this.property1 use:
my.somepackage.SomeClass.proper ty1
},
method2: function(){}
}
Referring back, can you answer the question why you need singleton when you have this solution? It serves you with no new possibilities, but definitely provides you with new pain in the ass.
Really my example is not that much of a static class but more like an instance of anonymous class, which makes it a only possible instance. And that makes the singleton pattern absolutely superfluous.
You have to understand that in javascript there really are no classes at all - this word is only used to describe things to guys comming from other languages.
thanks for your post.
Here is mine, based on your Singleton, using prototype syntax :
var Singleton = (function() {
var insRef;
var callnb;
var PrivateClass = Class.create({
initiali ze : function(url) { this.url=url;},
getcallnb : function() { return callnb; }
});
var PrivateGenerator = Class.create({
initialize : function() {
insRef = null;
callnb = 0;
},
getInstance : function(myurl) {
callnb++;
if (insRef == null) {
insRef = new PrivateClass (myurl);
//insRef .constructor = null; prevent new on copies of objects
//en effet, x1= Singleton.getInstance();
//z= new x1.constructor("une url") ; genre une instance de PrivateClass
}
return insRef ;
}
});
return new PrivateGenerator();
})();
<a href="http://www.universalutsi.com/">Static websites<a>
Write a new comment
<strong>,<em>,<cite>and<code>. Links, email addresses and line breaks are parsed automatically.