Skip to main content

A singleton is a class that will only ever have a single instance in your code, such as the Math object that exists within the JavaScript language itself. You cannot create new instances of this object, though it does contain properties and methods you can take advantage of in your code.

var User = function () {
  this.username = "";
  this.password = "";
  this.login = function () {
    return true;
  }
}

// -----------------------------------------------------------------------------
// Create an instance of the User class, storing it in the same variable used to
// define the class initially. The original class has now been removed from the
// code, leaving only the single object instance of it
// -----------------------------------------------------------------------------

User = new User();

// -----------------------------------------------------------------------------
// Example method call on the single instance of User
// -----------------------------------------------------------------------------

User.login();

// -----------------------------------------------------------------------------
// Example of a self-instantiating class
// -----------------------------------------------------------------------------

var Inbox = new function () {
  this.messageCount = 0;
  this.refresh = function () {
    return true;
  }
  }();

// -----------------------------------------------------------------------------
// The new keyword and braces force the function to immediately execute,
// meaning the Inbox variable now contains the single object instance, not the 
// class. Example method call on the single instance of Inbox.
// -----------------------------------------------------------------------------

Inbox.refresh();

// =============================================================

/**
 * The Singleton Pattern
 *
 * The Singleton pattern is thus known because it restricts instantiation of a
 * class to a single object. Classically, the Singleton pattern can be
 * implemented by creating a class with a method that creates a new instance
 * of the class if one doesn't exist. In the event of an instance already
 * existing, it simply returns a reference to that object.
 *
 * Singletons differ from static classes (or objects) as we can delay their
 * initialization, generally because they require some information that may
 * not be available during initialization time. They don't provide a way for
 * code that is unaware of a previous reference to them to easily retrieve
 * them. This is because it is neither the object or "class" that's returned
 * by a Singleton, it's a structure. Think of how closured variables aren't
 * actually closures - the function scope that provides the closure is the
 * closure.
 *
 * In JavaScript, Singletons serve as a shared resource namespace which
 * isolate implementation code from the global namespace so as to provide a
 * single point of access for functions.
 *
 * We can implement a Singleton as follows:
 *
 * http://addyosmani.com/resources/essentialjsdesignpatterns/book/
 */
var mySingleton = (function () {
  'use strict';

  // 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

var badSingleA = myBadSingleton.getInstance();
var badSingleB = myBadSingleton.getInstance();
console.log(badSingleA.getRandomNumber() !== badSingleB.getRandomNumber()); // true


// Note: as we are working with random numbers, there is a
// mathematical possibility both numbers will be the same,
// however unlikely. The above example should otherwise still
// be valid.


mySingleton.getInstance = function () {
  'use strict';

  if (this._instance === null) {
    if (isFoo()) {
      this._instance = new FooSingleton();
    }
    else {
      this._instance = new BasicSingleton();
    }
  }
  return this._instance;
};