What is the simplest/cleanest way to implement the singleton pattern in JavaScript?
40 Answers
I think the easiest way is to declare a simple object literal:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
If you want private members on your singleton instance, you can do something like this:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// All private members are accessible here
},
publicMethod2: function () {
}
};
})();
This has been called the module pattern, and it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.
If you want to prevent the modification of the singleton object, you can freeze it, using the ES5 Object.freeze method.
That will make the object immutable, preventing any modification to the its structure and values.
If you are using ES6, you can represent a singleton using ES Modules very easily, and you can even hold private state by declaring variables at the module scope:
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Then you can simply import the singleton object to use it:
import myInstance from './my-singleton.js'
// ...
I think the cleanest approach is something like:
var SingletonFactory = (function(){
function SingletonClass() {
//do stuff
}
var instance;
return {
getInstance: function(){
if (instance == null) {
instance = new SingletonClass();
// Hide the constructor so the returned object can't be new'd...
instance.constructor = null;
}
return instance;
}
};
})();
Afterwards, you can invoke the function as
var test = SingletonFactory.getInstance();
I'm not sure I agree with the module pattern being used as a replacement for a singleton pattern. I've often seen singletons used and abused in places where they're wholly unnecessary, and I'm sure the module pattern fills many gaps where programmers would otherwise use a singleton. However, the module pattern is not a singleton.
Module pattern:
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Everything initialized in the module pattern happens when Foo is declared. Additionally, the module pattern can be used to initialize a constructor, which could then be instantiated multiple times. While the module pattern is the right tool for many jobs, it's not equivalent to a singleton.
Singleton pattern:
short formvar Foo = function () {
"use strict";
if (Foo._instance) {
// This allows the constructor to be called multiple times
// and refer to the same instance. Another option is to
// throw an error.
return Foo._instance;
}
Foo._instance = this;
// Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
long form, using module pattern
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
// Instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
In both versions of the singleton pattern that I've provided, the constructor itself can be used as the accessor:
var a,
b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true
If you don't feel comfortable using the constructor this way, you can throw an error in the if (instance) statement, and stick to using the long form:
var a,
b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true
I should also mention that the singleton pattern fits well with the implicit constructor function pattern:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
// If the function wasn't called as a constructor,
// call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor
In ES6 the right way to do this is:
class MyClass {
constructor() {
if (MyClass._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error
Or, if you don't want an error to be thrown on the second instance creation, you can just return the last instance, like so:
class MyClass {
constructor() {
if (MyClass._instance) {
return MyClass._instance
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass()
var instanceTwo = new MyClass()
console.log(instanceOne === instanceTwo) // Logs "true"
In ECMAScript 2015 (ES6):
class Singleton {
constructor () {
if (!Singleton.instance) {
Singleton.instance = this
}
// Initialize object
return Singleton.instance
}
// Properties & Methods
}
const instance = new Singleton()
Object.freeze(instance)
export default instance
The following works in Node.js version 6:
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
We test:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
If you're using node.JS then you can take advantage of node.JS caching mechanism and your Singleton will be as simple as:
class Singleton {
constructor() {
this.message = 'I am an instance';
}
}
module.exports = new Singleton();
Please note that we export not the class Singleton but instance Singleton().
Node.JS will cache and reuse the same object each time it’s required.
For more details please check: Node.JS and Singleton Pattern
The simplest/cleanest for me means also simply to understand and no bells & whistles as are much discussed in the Java version of the discussion:
What is an efficient way to implement a singleton pattern in Java?
The answer that would fit simplest/cleanest best there from my point of view is:
Jonathan's answer to What is an efficient way to implement a singleton pattern in Java?
And it can only partly be translated to JavaScript. Some of the difference in JavaScript are:
- constructors can't be private
- Classes can't have declared fields
But given the latest ECMA syntax, it is possible to get close with:
Singleton pattern as a JavaScript class example
class Singleton {
constructor(field1,field2) {
this.field1=field1;
this.field2=field2;
Singleton.instance=this;
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance=new Singleton('DefaultField1','DefaultField2');
}
return Singleton.instance;
}
}
Example Usage
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Example Result
DefaultField1
DefaultField2
If you want to use classes:
class Singleton {
constructor(name, age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
}
let x = new Singleton('s', 1);
let y = new Singleton('k', 2);
Output for the above will be:
console.log(x.name, x.age, y.name, y.age) // s 1 s 1
Another way of writing Singleton using function
function AnotherSingleton (name,age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
let a = new AnotherSingleton('s', 1);
let b = new AnotherSingleton('k', 2);
Output for the above will be:
console.log(a.name, a.age, b.name, b.age) // s 1 s 1
There is more than one way to skin a cat :) Depending on your taste or specific need you can apply any of the proposed solutions. I personally go for Christian C. Salvadó's first solution whenever possible (when you don't need privacy).
Since the question was about the simplest and cleanest, that's the winner. Or even:
var myInstance = {}; // Done!
This (quote from my blog)...
var SingletonClass = new function() {
this.myFunction() {
// Do stuff
}
this.instance = 1;
}
doesn't make much sense (my blog example doesn't either) because it doesn't need any private variables, so it's pretty much the same as:
var SingletonClass = {
myFunction: function () {
// Do stuff
},
instance: 1
}
I deprecate my answer, see my other one.
Usually the module pattern (see Christian C. Salvadó's answer) which is not the singleton pattern is good enough. However, one of the features of the singleton is that its initialization is delayed till the object is needed. The module pattern lacks this feature.
My proposition (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Which compiled to this in JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Then I can do following:
window.iAmSingleton = singleton(function() {
/* This function should create and initialize singleton. */
alert("creating");
return {property1: 'value1', property2: 'value2'};
});
alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
I got this example from the *JavaScript Patterns Build Better Applications with Coding and Design Patterns book (by Stoyan Stefanov). In case you need some simple implementation class like a singleton object, you can use an immediate function as in the following:
var ClassName;
(function() {
var instance;
ClassName = function ClassName() {
// If the private instance variable is already initialized, return a reference
if(instance) {
return instance;
}
// If the instance is not created, save a pointer of the original reference
// to the private instance variable.
instance = this;
// All constructor initialization will be here
// i.e.:
this.someProperty = 0;
this.someMethod = function() {
// Some action here
};
};
}());
And you can check this example by following test case:
// Extending defined class like singleton object using the new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
// Extending the defined class like a singleton object using the new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
// Testing makes these two objects point to the same instance
console.log(obj_1 === obj_2); // Result is true, and it points to the same instance object
// All prototype properties work
// no matter when they were defined
console.log(obj_1.nothing && obj_1.everything
&& obj_2.nothing && obj_2.everything); // Result true
// Values of properties which are defined inside of the constructor
console.log(obj_1.someProperty); // Outputs 0
console.log(obj_2.someProperty); // Outputs 0
// Changing property value
obj_1.someProperty = 1;
console.log(obj_1.someProperty); // Output 1
console.log(obj_2.someProperty); // Output 1
console.log(obj_1.constructor === ClassName); // Output true
This approach passes all test cases while a private static implementation will fail when a prototype extension is used (it can be fixed, but it will not be simple) and a public static implementation less advisable due to an instance is exposed to the public.
Short answer:
Because of the non-blocking nature of JavaScript, singletons in JavaScript are really ugly in use. Global variables will give you one instance through the whole application too without all these callbacks, and module pattern gently hides internals behind the interface. See Christian C. Salvadó's answer.
But, since you wanted a singleton…
var singleton = function(initializer) {
var state = 'initial';
var instance;
var queue = [];
var instanceReady = function(createdInstance) {
state = 'ready';
instance = createdInstance;
while (callback = queue.shift()) {
callback(instance);
}
};
return function(callback) {
if (state === 'initial') {
state = 'waiting';
queue.push(callback);
initializer(instanceReady);
} else if (state === 'waiting') {
queue.push(callback);
} else {
callback(instance);
}
};
};
Usage:
var singletonInitializer = function(instanceReady) {
var preparedObject = {property: 'value'};
// Calling instanceReady notifies the singleton that the instance is ready to use
instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// Get the instance and use it
s(function(instance) {
instance.doSomething();
});