Working with Singletons in JavaScript

Vijay Prasanna

The Singleton is one of the most well known and hated design patterns amongst developers. It is very easy to implement a basic version of the singleton pattern (probably why it’s abused so much). In this article, we’ll take a look at what singletons are and how to best implement them in JavaScript.

There are times when you need to have only one instance of a class and no more. It could be some kind of resource manager, one that maintains I/O ports of your application or some global lookup for values. That’s where singletons come in.

Singletons are used to create an instance of a class if it does not exist or else return the reference of the existing one. In other words, Singletons are created exactly once during the runtime of the application in the global scope.

You might ask, why use singletons in a language with global variables? They don’t seem very different from global variables (or static ones), and most regard them as “glorified globals”. JavaScript in particular has that difference very very blurred, because the following code…

var Alliagator = {
  color: "green", 
  getColor: function() { 
    console.log(color);
  };
}

Is technically a singleton object, since it’s an object literal - which means that the object with that name is unique throughout the application (since it can’t be redeclared).

This seems to have a lot in common with global variables in JavaScript as well. So what’s the difference?

  • For starters, global variables are lexically scoped whereas singletons are not, meaning if there is another variable with the same name as the global variable inside a programming block, then that reference is given priority; In case of singletons, being sort of static in declaration, should not have that reference redeclared.
  • The value of a singleton is modified through methods.
  • The singleton is not freed until the termination of the program, which is likely not the case for a global variable.

An interesting advantage of a singleton is that it’s thread-safe. While that feature is not really applicable to Javascript, this comes in handy in languages like C++. This is just a case to prove the point that it’s not really weird to go for singletons even in a language that supports global variables.

There are scenarios where singletons are handy. Some applications of singletons are logger objects or configuration settings classes.

A quick way to declare a singleton would be:

// Declare them like this
var SingletonInstance = { 
 method1: function () { ... }
 method2: function () { ... } 
};

// and use them as such
console.log(SingletonInstance.method1());
console.log(SingletonInstance.method2());

While this may be the easy way, it’s not necessarily the best. Another way would be to use factory classes that allows us to create a singleton once.

var SingletonFactory = (function(){
  function SingletonClass() {
    // ...
  }
  var instance;
  return {
    getInstance: function(){
      // check if instance is available
      if (!instance) {
        instance = new SingletonClass();
        delete instance.constructor; // or set it to null
      }
      return instance;
    }
  };
})();

This is better than the last example because the class definition is private and the constructor is deleted after the first instance creation, which helps us prevent duplicate singletons in the program. But the above approach looks a lot like the factory pattern.

Perhaps the cleanest approach is to use a combination of ES6 classes, const and Object.freeze():

class Singleton {
  constructor(){
   ...
  }

  method1(){
    ...
  }

  method2(){
    ...
  }
}

const singletonInstance = new Singleton();
Object.freeze(singletonInstance);

We can go a little further and write this singleton in a module and then export it with the ES6 export functionality.

export default singletonInstance;

Then use that singleton by importing it:

import mySingleton from './path-to-my-singleton-definition.js'; 
mySingleton.method_1() // Now use your singletons

So take your pick, find which approach works best for your application and puts readability first.

Conclusion

It’s quite likely that you will run into overwhelming online literature on how singletons are bad for object oriented designs. The idea is to use singletons where it doesn’t affect the state of the application, because if you fail to follow, then testing goes right out the window. This severely limits their usage in big applications. Most developers agree that global state is bad, but they love them too much to look at its bad sides while others go extreme lengths to avoid using global states. Whether singletons are good or bad, understanding this fundamental design pattern and adding it to your programming toolkit is always a wise idea.

Further Reading

Check out this blog post by Misko Hevery for more insight into the global state issue with singletons.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#