What is the simplest/cleanest way to implement singleton pattern in JavaScript?
@CMS and @zzzzBov have both given wonderful answers, but just to add my own interpretation based on my having moved into heavy node.js development from PHP/Zend Framework where singleton patterns were common.
The following, comment-documented code is based on the following requirements:
My code is very similar to @zzzzBov's except I've added a prototype chain to the constructor and more comments that should help those coming from PHP or a similar language translate traditional OOP to Javascripts prototypical nature. It may not be the "simplest" but I believe it is the most proper.
// declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
"use strict";
// 'instance' and 'constructor' should not be availble in a "public" scope
// here they are "private", thus available only within
// the scope of the self-executing anonymous function
var _instance=null;
var _constructor = function (name) {
this.name = name || 'default';
}
// prototypes will be "public" methods available from the instance
_constructor.prototype.getName = function () {
return this.name;
}
// using the module pattern, return a static object
// which essentially is a list of "public static" methods
return {
// because getInstance is defined within the same scope
// it can access the "private" 'instance' and 'constructor' vars
getInstance:function (name) {
if (!_instance) {
console.log('creating'); // this should only happen once
_instance = new _constructor(name);
}
console.log('returning');
return _instance;
}
}
})(); // self execute
// ensure 'instance' and 'constructor' are unavailable
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined
// assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
// ensure 'a' and 'b' are truly equal
console.log(a === b); // true
console.log(a.getName()); // "first"
console.log(b.getName()); // also returns "first" because it's the same instance as 'a'
Note that technically, the self-executing anonymous function is itself a Singleton as demonstrated nicely in the code provided by @CMS. The only catch here is that it is not possible to modify the prototype chain of the constructor when the constructor itself is anonymous.
Keep in mind that to Javascript, the concepts of “public” and “private” do not apply as they do in PHP or Java. But we have achieved the same effect by leveraging Javascript’s rules of functional scope availability.