JavaScript Singleton Pattern

Definition

Main purpose of singleton is to provide a single instance of a specific class. In terms of Javascript it means to have only one object of a certain type.

Such an object may be handy for things like:

  • Database drivers (which take care especially of connections)
  • Dialog boxes management
  • Ajax requests (in order not to exceed max number of requests)
  • Global settings (in order to have only one set of settings)

In statical typed OOP languages this is done by making constructor private and retrieving instance pointer via static public function. For example in JAVA:

public class Singleton {
  private static Singleton instance = null;

  private Singleton() {}

  public static Singleton getInstance() {
    if (instance == null) {
      instance = new Singleton ();
    }
    return instance;
  }
}

// Usage
Singleton.getInstance()

GoF’s applicability of singleton is described as:

  • There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
  • When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

The second point here refers to branching:

getInstance = function(){
  if (this.instance === null) {
    if (isIE()) {
       this.instance = new SingletonForIE()
    } else {
       this.instance = new SingletonForNonIE()
    }
  }
  return this.instance;
}

Branching looks like Factory pattern. It may be strange why it is used in here, but the reason is that there may be a lot of cases when you want to have different objects depending on environment but you want to check the environment only one time - on object initialisation.

Generally Singleton is considered to be an anti-pattern. Probably because of breaking single responsibility principle: every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. But usually Singleton has responsibility of assuring to be unique and one more which is its main purpose.

Basic JavaScript Singleton

Taking in account that in JavaScript you can instantiate a object without defining a class, the most simple singleton will look like:

Singleton = {}

There will be only one unique instance of this object. But it’s simplicity bring many possible drawbacks:

  • It can be rewritten
  • You must assure that it is instantiated before its first use
  • All its members will be public (easy to rewrite or remove)
  • If it will have a huge payload or some resource intensive tasks than it may block application initialisation

JavaScript has no classes, but it has keyword new which calls constructor function when object is instantiated. But this constructor can’t be set as private so the classical method will not work here. What we can actually do is to return object instance from constructor method if it was previously instantiated. This way object creation will look as usual s = new Singleton() and not s = Singleton.getInstance() as it is in Java (and many other languages). We’ll need to cache our object instance. We can use a global variable as a cache or prototype object.

Caching instance in a global variable isn’t much different from just having an object:

var instance
function Singleton(){
  if(instance !== undefined)
    return instance

  instance = this
}

The only benefits of this implementation are instantiation of object using new keyword and lazy instantiation. But this way we pollute global namespace. So let’s cache our instance in static attributes (attributes assigned to constructor):

function Singleton(){
  if(Singleton.instance !== undefined)
    return Singleton.instance

  Singleton.instance = this
}

which is almost the same as

function Singleton(){
  if(Singleton.prototype.instance !== undefined)
    return Singleton.prototype.instance

  Singleton.prototype.instance = this
}

The only difference between this 2 solutions is that in first case we store instance in constructor object, and in second case in prototype object. It may be important when using prototypal inheritance.

Now we don’t have to care about object instantiation before its first usage as in case with defining object using the literal syntax for object creation.

Overriding constructor

In order not to use prototype caching we can override constructor function at first instantiation:

function Singleton(){
  var instance = this

  // rewrite the constructor
  Singleton = function(){
    return instance
  }
}

// add param1 to prototype
Singleton.prototype.param1 = 1

s = new Singleton()

// add param2 to prototype
Singleton.prototype.param2 = 2

console.log(s.param1) // 1
console.log(s.param2) // undefined

But it has a huge drawback if you want to use prototype delegation. The problem is caused by the fact that the s’  prototype is originated from original constructor but not to the redefined. In order to overcome that we have to override new object’s prototype with the old one. Also we can override constructor  to be able to check object constructor.

function Singleton(){
  var instance = this

  // rewrite the constructor
  Singleton = function(){
    return instance
  }

  Singleton.prototype = this
  // optional
  this.constructor = Singleton
}

// add param1 to prototype
Singleton.prototype.param1 = 1

s = new Singleton()

// add param2 to prototype
Singleton.prototype.param2 = 2

console.log(s.param1) // 1
console.log(s.param2) // 2

s.constructor === Singleton // true

Private members

If we need to hide internals of our object than we can use:

  • Use a convention were all private members should start with an underscore
  • Return a new object from constructor (which has access to function scope variables)
  • Self invoking anonymous function which will return a Singleton object

Returning a new object from constructor and self invoking anonymous function are known as Module pattern because is modularizes and namespaces a set set of related methods and attributes. It is a simulation of private property. Both implementations have a drawback - we can’t use anymore prototype delegation via Singleton constructor function. However we can assign new members to any Singleton object and it will accessible from all object variables (as it is the same instance). This example uses lazy initialisation as the constructor body will be executed only when an instance will be created.

function Singleton(){
  if(Singleton.instance !== undefined)
    return Singleton.instance

  var privateMember = 1

  // All public methods
  Singleton.instance = {
    getMember: function(){
      return privateMember
    }
  }

  return Singleton.instance
}

s = new Singleton()

s.privateMember // undefined
s.getMember() // 1
s2 = new Singleton()

s.newMember = 2
s2.newMember // 2

Self invoking anonymous function returns an object with some hidden members. So it is pure Module pattern.

CoffeeScript Singleton Pattern

We can simply translate JS into CoffeeScript. This:

function Singleton(){
  if(Singleton.instance !== undefined)
    return Singleton.instance

  Singleton.instance = this
}

into this:

Singleton = ()->
  return Singleton.instance if Singleton.instance

  Singleton.instance = @

# testing
c = new Singleton()
d = new Singleton()
console.log c is d

In order to hide Singleton internals we can use classes closures:

class Singleton
  Singleton.instance = null
  # Private variable
  message = null

  # message is a private variable
  constructor: (message) ->
    Singleton.instance ?= new PrivateClass(message)
    return Singleton.instance

  class PrivateClass
    constructor: (_message)->
      message = _message
    echo: -> message

a = Singleton("Hello A")
console.log a.echo() # => "Hello A"

b = Singleton("Hello B")
console.log b.echo() # => "Hello A"

We can use a much simpler construction like:

class Singleton
  Singleton.instance = null

  constructor: () ->
    Singleton.instance ?= @
    return Singleton.instance

a = Singleton()
b = Singleton()
console.log a is b # => true

We can hide Singleton instance by redefining constructor:

class Singleton

  instance = new @()
  # message is a private variable
  constructor: () ->
    return instance

Singleton.prototype.p1 = 1
a = new Singleton()
Singleton.prototype.p2 = 2
b = new Singleton()

console.log a is b # => true
console.log a.p1 # => 1
console.log a.p2 # => 2

But in this case new constructor will be instantiated on Singleton definition. Also Coffee extend will not work anymore. In order to overcome it we may use an additional method that will return the instance:

class Singleton
  @instance: null
  @getInstance: ->
    @instance ?= new @()

class SingletonChild extends Singleton
  newMethod: () ->
    'result'

a = Singleton.getInstance()
b = Singleton.getInstance()

c = SingletonChild.getInstance()
d = SingletonChild.getInstance()

console.log a is b # true
console.log c is d # true
console.log a is c # false
console.log a.newMethod() # Object #<Singleton> has no method 'newMethod'
console.log c.newMethod() # result

The only benefit of this example over defining object using the literal syntax for object creation is CoffeeScript’s syntactic sugar of class definition and ability to have hidden attributes and methods. But if you don’t need all that you can do it in a much sore simple way by using plain objects:

Singleton =
  property: 1

SingletonChild = Object.create(Singleton)

SingletonChild.newProperty = 2

console.log Singleton.property         # 1
console.log SingletonChild.property    # 1
console.log Singleton.newProperty      # undefined
console.log SingletonChild.newProperty # 2

Sources

  1. (github) shichuan / javascript-patterns / design-patterns / singleton.html
  2. (book) Head First Design Patterns
  3. (book) Learning JavaScript Design Patterns
  4. (book) JavaScript Patterns: Build Better Applications with Coding and Design Patterns
  5. (book) Learning JavaScript Design Patterns: A JavaScript and jQuery Developer's Guide
  6. (book) Pro JavaScript Design Patterns: The Essentials of Object-Oriented JavaScript Programming
  7. (book) CoffeeScript Cookbook
  8. (article) The Singleton pattern in JavaScript: not needed
  9. (article) The singleton design pattern in javascript
  10. (article) JS Objects: De”construct”ion
  11. (question) How to create coffeescript singleton subclass