DEV Community

Cover image for Singleton Pattern in Javascript
Bibek
Bibek

Posted on • Updated on • Originally published at blog.bibekkakati.me

Singleton Pattern in Javascript

In this article, you will learn how to implement a singleton pattern in Javascript.

What is Singleton Pattern?

Singleton pattern is a design pattern that allows us to use a single instance of a class everywhere.

Implementation

We are creating an empty class MyClass for demonstration purpose.

class MyClass {
  ...
}

const Singleton = (function () {
  var instance;

  function createInstance() {
    var classObj = new MyClass();
    return classObj;
  }

  return {
    getInstance: function () {
        if (!instance) {
            instance = createInstance();
        }
        return instance;
    },
  };
})();

module.exports = Singleton;
Enter fullscreen mode Exit fullscreen mode

The Singleton object is implemented as an IIFE.

An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.

The createInstance function is responsible for creating the instance of MyClass.

The getInstance method will be invoked via the Singleton object. If the instance of MyClass is not present it will be created and returned, if already present it will return directly without creating a new instance.

So this pattern allows us to access and manipulate the members of a class instance from any file or function.

Example

Let's create a class in a separate file.

// Filename: Username.js

module.exports.Username = class Username {
    constructor() {
        this._username;
    }

    set username(value) {
        this._username = value;
    }

    get username() {
        return this._username;
    }
};

Enter fullscreen mode Exit fullscreen mode

We are using getter and setter to access and set the value of the _username.

Now we will create a file for the Singleton object.

// Filename: singleton.js

const { Username } = require("./Username");

const Singleton = (function () {
    var instance;

    function createInstance() {
        var classObj = new Username();
        return classObj;
    }

    return {
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        },
    };
})();

module.exports = Singleton;
Enter fullscreen mode Exit fullscreen mode

Here, we are importing the Username class and creating its instance with the help of the Singleton object.

At last, we will create a index.js file to run the program.

// Filename: index.js

const Singleton = require("./Singleton");

function main() {
    var instanceOne = Singleton.getInstance();
    instanceOne.username = "Jack";

    var instanceTwo = Singleton.getInstance();
    console.log("Second Instance: ", instanceTwo.username);
    // Output - Second Instance:  Jack

    console.log("Are both instance equal? ", instanceOne === instanceTwo);
    // Output - Are both instance equal?  true
}

main();
Enter fullscreen mode Exit fullscreen mode

As you can see, first we call the instance of the Username class from the Singleton object and assigning it to variable instanceOne.
Then we set the username from instanceOne.

Again, we call the instance of Username class from Singleton object and this time we are assigning it to another variable instanceTwo. And in the output, we can see that the value of username is the same as we set it through instanceOne.

When we compared if both instances are equal, it returns true.

Conclusion

Singleton object is not creating any new instance every time we call it, instead, it returns the previous instance of the class. Hence, this design pattern is very useful in many cases like using a common database connection etc.

Github Repo Link

Thank you for reading. Give it a thumbs-up if it is helpful for you.

Feel free to connect 👋


Originally published on blog.bibekkakati.me


Thank you for reading 🙏

If you enjoyed this article or found it helpful, give it a thumbs-up 👍

Feel free to connect 👋

Twitter | Instagram | LinkedIn


If you like my work and want to support it, you can do it here. I will really appreciate it.



Top comments (9)

Collapse
 
belkheir profile image
Mahamed Belkheir

Honestly, Singleton is that one pattern that doesn't make much sense to use in a language like Javascript where you can create one-off object instances without a class and define functionality for it.

The Singleton's getInstance pattern is more useful in languages like Java where managing when an instance is created and used is a bit more painful, but in js you can easily make sure a single instance is created by declaring it on the package scope, any further imports do not re-run the file, and it just uses the same instance.

Collapse
 
andi23rosca profile image
Andi Rosca • Edited

I agree. Singletons are less of a design pattern and more of a work-around for the limitation of languages that only let you use classes and nothing else.

And apart from some sense of "this must be readable because I'm using design patterns" I think most people will find

// Singleton.js
export const Singleton = { name: "John" };
// some other file
import { Singleton } from "...";
Enter fullscreen mode Exit fullscreen mode

way more readable than the 2 different files presented in the example, with so much ceremony around what you are actually trying to accomplish.

Collapse
 
bibekkakati profile image
Bibek

Hey Mahamed Belkheir, you are right we can create one-off object instance directly. I prefer to follow the common implementation way of these design patterns. It also helps to understand the code better if someone is coming from other language. At last, in javascript we have two choices, modularisation approach or singleton approach.

Collapse
 
mindplay profile image
Rasmus Schultz

The singleton pattern is an anti pattern - see the "Criticism" section in the Wikipedia article for a brief summary of all the reasons why:

en.wikipedia.org/wiki/Singleton_pa...

Teaching this pattern without a clear warning should be considered harmful - using this pattern will lead to endless refactoring and makes your software untestable.

Please look up articles about dependency injection, and inversion of control, and learn that instead.

Collapse
 
chanhenghong profile image
Chanheng Hong

Thank for this article.

Collapse
 
chayimfriedman2 profile image
Chayim Friedman • Edited

I would do it this way:

const Singleton = (function() {
    let instance = null;
    return class Singleton {
        constructor() {
            if (instance !== null) { return instance; }
            instance = this;
            // Init properties...
        }
        // ...
    };
})();
Enter fullscreen mode Exit fullscreen mode

Allowing you to use new:

console.log(new Singleton() === new Singleton()); // true
Enter fullscreen mode Exit fullscreen mode

Of course it can be done without ES6 classes too:

const Singleton = (function() {
    let instance = null;
    return function Singleton() {
        if (!new.target) { throw new Error("`Singleton()` must be called with `new`"); }
        if (instance !== null) { return instance; }
        instance = this;
        // Init properties and set methods...
    };
})();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
bibekkakati profile image
Bibek

Yeah, that can be a way of implementing it.

Collapse
 
devdufutur profile image
Rudy Nappée

With ES6 modules you have ready to use singletons 😉

Collapse
 
bibekkakati profile image
Bibek

Yeah, we can achieve same thing with modularisation approach but if you want to go with a standard design pattern then Singleton is there 😁.