The Singleton Pattern is one of the most used patterns in almost all of the programming languages, and some consider it an anti-pattern (more on that later). The Singleton Pattern states that the number of instances of an object must be restricted to one only, hence the "single" in Singleton.

According to the most famous book on design patterns; Design Patterns: Elements of Reusable Object-Oriented Software, the intent of the Singleton is the following.

Ensure a class has only one instance, and provide a global point of access to it.

The Singleton Pattern falls under the creational design patterns category.

Singleton In JavaScript

It is implemented in the classical OO languages by defining a method in the class which creates a new instance of the class only if there is no existing instance of it. Otherwise, the method returns a reference to the existing instance.

Classical languages like Java, C#, and C++ have namespace. While JavaScript doesn't have this features, developers tend to utilize Singletons to serve this purpose. Singletons isolate implementation from the global namespace.

Let's take example on implementing Singletons in ES5 and ES2015.

ES5 Implementation

Already Using Singletons

The following piece of code is a JavaScript developer's daily usage of the Singleton.

var obj = {  
  foo: 'Foo',
  bar: 'Bar',
  fooBar: function() {
    return this.foo + ' ' + this.bar;
  }
};

jQuery is an example of the Singleton Pattern. The $ encapsulate the jQuery functions in one namespace which one can use anywhere in the application.

As Module

Addy Osmani defined the Singleton pattern in his great book about design patterns like the following.

var mySingleton = (function () {
 
  // Instance stores a reference to the Singleton
  var instance;
 
  function init() {
 
    // Singleton
 
    // Private methods and variables
    function privateMethod(){
        console.log( "I am private" );
    }
 
    var privateVariable = "Im also private";
 
    var privateRandomNumber = Math.random();
 
    return {
 
      // Public methods and variables
      publicMethod: function () {
        console.log( "The public can see me!" );
      },
 
      publicProperty: "I am also public",
 
      getRandomNumber: function() {
        return privateRandomNumber;
      }
 
    };
 
  };
 
  return {
 
    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function () {
 
      if ( !instance ) {
        instance = init();
      }
 
      return instance;
    }
 
  };
 
})();
 
var myBadSingleton = (function () {
 
  // Instance stores a reference to the Singleton
  var instance;
 
  function init() {
 
    // Singleton
 
    var privateRandomNumber = Math.random();
 
    return {
 
      getRandomNumber: function() {
        return privateRandomNumber;
      }
 
    };
 
  };
 
  return {
 
    // Always create a new Singleton instance
    getInstance: function () {
 
      instance = init();
 
      return instance;
    }
 
  };
 
})();
 
 
// Usage:
 
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); // true

It is noticeable that this is an implementation of the Module Pattern that was covered previously. By defining it that way, we can have private and public methods for the Singleton.

As Addy has stated:

What makes the Singleton is the global access to the instance (generally through MySingleton.getInstance()) as we don't (at least in static languages) call new MySingleton() directly. This is however possible in JavaScript.

Closure

This way of implementing the Singleton is less "verbose." It's another constructor based implementation using JavaScript's closures.

function Singleton() {
  // Instance stores a reference to the Singleton
  var instance;

  // Singleton
  Singleton = function() {
    return instance;
  };

  // carry over the prototype
  Singleton.prototype = this;

  // the instance
  instance = new Singleton();

  // reset the constructor pointer
  instance.constructor = Singleton;

  // variable
  instance.publicVariable = 'Public Variable';
  
  // function
  instance.publicMethod = function () {
    console.log('Public Method');
  };

  return instance;
}

ES2015 Implementation

Now that we have ES2015/ES6 features mostly in all the major browsers and Node.js, we can start using them to utilize the Singleton Pattern using a class or an object literal with const.

Using Classes

Despite the hate to the ES6's classes, it is something I have seen many developers use. Anyways, classes in JavaScript is just syntactic sugar.

class Singleton {
  constructor() {
    // the class constructor
    if(! Singleton.instance){
      Singleton.instance = this;
    }
    return Singleton.instance;
  }

  publicMethod() {
    console.log('Public Method');
  }
}

const instance = new Singleton();

// prevents new properties from being added to the object
Object.freeze(instance);

export default instance;

In the constructor, we check if the there is no instance of the class exists, we assign this to Singleton.instance and then return the instance. This approach is close to the one in classical OO languages.

Using Object Literal

I understand if the JavaScript's classes are not your thing. Therefore, there is the object literal approach. Here is an example.

const Singleton = {
  publicMethod: () => console.log('Public Method')
}

Object.freeze(Singleton);
export default Singleton;

Using Singleton Pattern

It is almost in all languages the Singleton Pattern considered an anti-pattern. Here is what Addy Osmani said about it in his book.

Whilst the Singleton has valid uses, often when we find ourselves needing it in JavaScript it's a sign that we may need to re-evaluate our design.
They're often an indication that modules in a system are either tightly coupled or that logic is overly spread across multiple parts of a codebase. Singletons can be more difficult to test due to issues ranging from hidden dependencies, the difficulty in creating multiple instances, difficulty in stubbing dependencies and so on.