A few (of the many) different ways to create a Singleton in JavaScript. Be warned some of these examples require a lot more code to make them true Singletons. As is the case with most problems: simplicity is the key.
function Universe() {
// do we have an existing instance?
if (typeof Universe.instance === "object") {
return Universe.instance;
}
// proceed as normal
this.start_time = 0;
this.bang = "Big";
// public methods
this.setTime = function(time){
this.start_time = time;
}
// cache (warning this property is public and so can be modified!)
Universe.instance = this;
}
// testing
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
// view each instance to see their value
console.log(uni.start_time);
console.log(uni2.start_time);
// update the value for the first instance
uni.setTime(123);
// see both instances have updated (which means although different instances were created, the object is still a Singleton
console.log(uni.start_time);
console.log(uni2.start_time);
Singleton_2.js
function Universe() {
// the cached instance
var instance = this;
// proceed as normal
this.start_time = 0;
this.bang = "Big";
// public methods
this.setTime = function(time){
this.start_time = time;
}
// rewrite the constructor
Universe = function () {
return instance;
};
}
// testing
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
// view each instance to see their value
console.log(uni.start_time);
console.log(uni2.start_time);
// update the value for the first instance
uni.setTime(123);
// see both instances have updated (which means although different instances were created, the object is still a Singleton
console.log(uni.start_time);
console.log(uni2.start_time);
Singleton_3.js
var Singleton = (function(){ // We use a 'immediately invoked function expression' to create a Closure.
// Private attribute that holds the single instance
var uniqueInstance;
// Private method which holds all of the normal Singleton code
function Constructor(){
// Private members (can't be accessed directly)
var privateAttribute1 = false;
var privateAttribute2 = [1, 2, 3];
// Private method (can't be accessed directly)
function privateMethod(){
return 'my private method';
}
return {
publicAttribute1: true,
publicAttribute2: 10,
// This method can be referred to as a 'Privileged' method as it has access to Private areas
publicMethod: function(){
console.log('privateMethod() = ' + privateMethod()); // privileged access
console.log('privateAttribute1 = ' + privateAttribute1); // privileged access
console.log('privateAttribute2 = ' + privateAttribute2); // privileged access
console.log('this.publicAttribute1 = ' + this.publicAttribute1);
console.log('this.publicAttribute2 = ' + this.publicAttribute2);
}
}
}
return {
getInstance: function(){
// Instantiate only if the instance doesn't exist.
if (!uniqueInstance) {
uniqueInstance = Constructor();
}
return uniqueInstance;
}
}
})();
/**
* Now this singleton uses 'lazy loading' we must make sure we use the correct function calls
*
* e.g.
* Singleton.getInstance().publicMethod1();
*
* Notice we can 'chain' the methods because 'getInstance' returns the function object itself rather than a value.
*/
Singleton.getInstance().publicMethod();