This article will demonstrate how to create a singleton for use in Javascript programs.
In object oriented programming, a singleton is a class that is instantiated only once. Most programmers find the idea of a singleton counter-intuitive when first introduced to them. Most of the time, we create classes so we can create many instances of them; after all, it doesn't make much sense to create a database application that can work with only a single employee at a time.
However, there are times when we want to create a system within a program; for example, let's pretend we're writing a game and want to create a sound system. In a procedural language like C, we'd create a series of functions all prefixed with the same value.
/* This is a comment, i.e. ignored by the computer */
/* Procedural sound system example */
void soundsys_init( void ){
/* Proper code */
}
void soundsys_start( void ){
/* Proper code */
}
void soundsys_stop( void ){
/* Proper code */
}
The sound system might be used elsewhere in the program like so:
/* Using the procedural sound system */ soundsys_init(); /* Init our sound system */ /* Chunk of program code */ soundsys_start(); /* Play a sound */ /* Chunk of program code */ soundsys_stop(); /* Stop playing sound */
The problem with this style of programming is it becomes messy. There are many functions exposed globally. Any variables that are to be shared between functions must also be created globally. A singleton is the object oriented method we use to wrap everything up nice and neat.
Creating a singleton in Javascript requires nothing more than an anonymous function and an object literal.
An object literal is nothing more than a comma-delimited list of name-value pairs enclosed in curly braces; the Javascript intepreter creates an object whenever an object literal is encountered. Separate names from values with a colon and don't forget to separate name-value pairs with commas.
// Creating an object using an object literal, 1 property
var obj1 = { prop : "Hello, World!" };
alert(obj1); // Will display 'object'
alert(obj1.prop); // Will display 'Hello, World!'
// Creating an object with multiple properties
var obj2 = { prop1 : "Hello, World!",
prop2 : "Goodbye, World!" };
alert(obj2.prop1); // Will display 'Hello, World!'
alert(obj2.prop2); // Will display 'Goodbye, World!'
// Creating an object with properties and methods
var obj3 = { prop1 : "Some property",
method1 : function(){
return this.prop1;
}
};
alert(obj3.method1()); // Will display 'Some property'
An anonymous function is one which doesn't have a name; it may or may not be stored inside of a variable.
// Creating an anonymous function and storing it in a variable
var func = function(){
alert("A function!");
}
// Calling the function
func(); // Will display 'A function!'
// Creating an anonymous function and executing it on the spot;
// notice the extra two pairs of open-close parentheses and the
// semi-colon.
(function(){
alert("A function!");
})();
It is the second anonymous function that is of most interest to us. It will be evaluated and called on the spot and there is no means of executing the function a second time. We don't have any reference to the function, either by name or through a variable.
In order to create a singleton, we just return an object from the second anonymous function above.
// Create a simple singleton
var Singleton = (function(){
var obj = {
prop : "value";
};
return obj;
})();
// We've now created a singleton named 'Singleton'
alert(Singleton); // Will display 'object'
alert(Singleton.prop); // Will display 'value'
As it stands, our singleton isn't very interesting. Let's start by adding some internal "constants;" I use double quotes because they're not really constant.
// Create a simple singleton
var Singleton = (function(){
var obj = {
// "Constants"
STATE_INIT : 0x01, // State initialize
STATE_READY : 0x02, // State ready
STATE_ERROR : 0x04, // State error
};
return obj;
})();
Typically you will need to keep track of values within your singleton; I like to prefix mine with an underscore.
// Create a simple singleton
var Singleton = (function(){
var obj = {
// The constants...
// Properties
_state : this.STATE_INIT, // Set initial state
_errmsg : null, // Current error message
};
return obj;
})();
Now we will add a couple of methods to our singleton.
// Create a simple singleton
var Singleton = (function(){
var obj = {
// The constants...
// The properties...
/**
* getErrorMsg
* Return the current error message
*/
getErrorMsg : function(){
return this._errmsg;
},
/**
* clearErrorMsg
* Clear the current error message
*/
clearErrorMsg : function(){
this._errmsg = null;
}
};
return obj;
})();
For reference, here is our complete example singleton.
// Create a simple singleton
var Singleton = (function(){
var obj = {
// "Constants"
STATE_INIT : 0x01, // State initialize
STATE_READY : 0x02, // State ready
STATE_ERROR : 0x04, // State error
// Properties
_state : this.STATE_INIT, // Set initial state
_errmsg : null, // Current error message
/**
* getErrorMsg
* Return the current error message
*/
getErrorMsg : function(){
return this._errmsg;
},
/**
* clearErrorMsg
* Clear the current error message
*/
clearErrorMsg : function(){
this._errmsg = null;
}
};
return obj;
})();
So our example singleton isn't very useful, but I think it gets the point across. Hopefully you found this article helpful and can find some creative uses for singletons within your own applications.
Comments
Nice
Hi Robert, nice tut.
It's a bit weird to see a Singleton like this (some would argue that it's simply a global object reference), but then again, much JavaScript OO is a bit 'weird'... :P
Maybe you should add a little about private props?
Thanks
Hi John,
I wasn't aware you could create private properties in JavaScript; a quick search lead me to this:
http://www.crockford.com/javascript/private.html
As far as the global object reference, that's all it really is. But this method of instantiating and using the object is perfect for my uses.
Post new comment