DEV Community

Singleton in JavaScript

Tomek Buszewski on December 05, 2018

Hello, Yesterday I wrote my first technical article ever! It is about singleton design pattern in JavaScript. I put it on Reddit and got some negat...
Collapse
 
avalander profile image
Avalander

What is the advantage of using a class for a singleton versus let's say using an object literal?

const mySingleton = {
    name: 'One',
    getName () {
        return this.name
    }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tomekbuszewski profile image
Tomek Buszewski

This is a design pattern (object literal is also one, more specific to the JS). Difference is for example that literal can be extended.

Collapse
 
avalander profile image
Avalander

In which way can you extend an object literal that you cannot extend your singleton object?

Thread Thread
 
tomekbuszewski profile image
Tomek Buszewski

Sorry, I meant not extending but inherit. You can inherit from object literals by just creating new object based on your original one, like here. In singleton pattern, once you create the instance, it cannot be inherited in any way, because any ancestors will link to the original one.

Sorry again for confusion, lack of sleep has really got me this time :D

Thread Thread
 
avalander profile image
Avalander

That's not what I would define as inheriting, you're cloning the object and adding extra properties to the clone. Nothing prevents anyone from cloning your singleton instance either, though, as long as they remember to carry on the prototype.

const clone = Object.assign(
    Object.create(SingletonClass.prototype),
    instanceOne,
    { shoutName() { return this.name.toUpperCase() }}
)

console.log(clone.shoutName())
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
tomekbuszewski profile image
Tomek Buszewski

You are completely right, but here you are stepping away from the merit of the text, which is singleton design pattern. In JavaScript all (or are there some that aren't?) reference types can be cloned and those cloned modified.

Collapse
 
bgadrian profile image
Adrian B.G. • Edited

While, by some, seen as an anti-pattern, it is worth knowing something about it.

Everyone should see it like that, I think it is even mentioned in antipattern book. The good thing is that most of its downsides can be avoided by allowing anyone to make an instance (making the constructor public) and have an interface (in the languages where they exists).

This way you can:

  • make instances for testing
  • inherit it if necessary (open for extension)
  • can build mockups/stubs for proper testing

Making a singleton has its own problems, but the biggest issues arrive when you are using the instance directly, as a global static instance. This will create hard dependencies, spaghetti code, impossible to test and extend code.

In JS you can avoid these issues by making them as module dependencies, and keep the singleton instance inside a module, at init. But when required, you can inject a mock/stub/replacement in other modules. The best examples are the Window/Nodejs environments that are used as examples in the modules.

PS: is good to have one single instance of an entity (ex: configs, database connections and so on), but do not use them directly, send them as parameters to functions/modules (injection).

Collapse
 
tomekbuszewski profile image
Tomek Buszewski

I haven't used singletons in a while, but I remember it being quite useful when I was building services for sensitive DOM manipulation and listening. You create a listener in a constructor and this guarantee that this is the only one available. But, like I said, this can be done in a myriad of other ways and I have written this strictly as an informative post.

Collapse
 
coly010 profile image
Colum Ferry

Angular uses Singletons a lot. They provide a TypeScript decorator called: @Injectable which turns whichever class is decorated into a Singleton.

The use-case in Angular is logic services. Sure you can use them to maintain state in your App but it can be messy, bug-prone and hairy if you do not take great care in doing so.
However, on the flip side, if you have a class whose function is to provide pure methods or to fetch data from a data-source, then why should you need multiple instances of this class.

In fact, having multiple instances will take up memory within your app. This could be dangerous!
If you do maintain state in your service, perhaps you want to know the loggedInUser, having a singleton for this makes perfect sense. You should only have one logged in user and therefore your singleton will only ever return this one user.

Collapse
 
dance2die profile image
Sung M. Kim

If I may, I'd like to shamelessly plug my post about another valid usage of Singleton pattern 😛

The gist is that, Singleton pattern works great in combination with a Null pattern (where the null object is implemented as a singleton).

Collapse
 
dance2die profile image
Sung M. Kim • Edited

Thank you for the post Tomek.

I've never implemented singleton in JavaScript and found it interesting 🙂

Is there a way to prevent a singleton class to be newed up in JavaScript?
In C#, one can declare a constructor as private, constraining people to use ClassName.instance.

Collapse
 
tomekbuszewski profile image
Tomek Buszewski

Hi, and thanks foe your kind words!

JavaScript doesn't have private and public distinction (yet), so the short answer is - no.

The long one is - you can have private methods in TypeScript (and, private constructor). I've created a simple demo and – while TypeScript linter shouts that this is an error (noting that constructor is indeed private), this gets compiled to JavaScript as a regular class that can have multiple instances. So I guess it's the compiler's job to fail here.

Collapse
 
dance2die profile image
Sung M. Kim

Thanks Tomek for the follow-up~ 🙏

That sounds like another great reason to use TypeScript 🙂

Thread Thread
 
tomekbuszewski profile image
Tomek Buszewski

Yes, TypeScript is a great tool and I use it recently for almost everything. The best thing is, it's JavaScript superset, so you don't really have to know everything and can just build your knowledge while working on a project. Create a plain JS code then slowly fill the type coverage as you go :)

Collapse
 
smalluban profile image
Dominik Lubański • Edited

Regardless singleton is right or not, there is a way to create a class, that can be extended and be a singleton for own type only.

Instead of using hard reference class constructor you should use constructor property of the instance.

class SingletonClass {
    constructor(name = "") {
        if (!!this.constructor.instance) {
            return this.constructor.instance;
        }

        this.constructor.instance = this;

        return this;
    }
}

this.constructor is a reference to the direct constructor function.

Collapse
 
tomekbuszewski profile image
Tomek Buszewski • Edited

I'm not sure I understood you correctly, you mean using this I can create another class that will extend the SingletonClass? Then SingletonClass isn't a singleton, because, by definition, it cannot be extended.

Plus, I have tried something like this and failed, can you provide the code?

Collapse
 
smalluban profile image
Dominik Lubański

I forgot about constructors prototype chain :P

Here you have working example:

Thread Thread
 
tomekbuszewski profile image
Tomek Buszewski

This is not a singleton class now :) But nevertheless, excellent example.

Collapse
 
manpenaloza profile image
Manuel Penaloza

Very nice!

Collapse
 
juanlanus profile image
Juan Lanus

My application has a potentially very long list of materials, to be used anywhere within the ReactJS components hierarchy.
I want to load it only once, and to have it available everywhere.

For this purpose I'm writing an ES6 class to be instantiated as a singleton, sitting in global state with reactn.
This post clarified the way to code the singleton thimg, big time.

Collapse
 
somedood profile image
Basti Ortiz

Cool! Nice and simple explanation. Great job!

Collapse
 
tomekbuszewski profile image
Tomek Buszewski

Thanks a lot :)

Collapse
 
somedood profile image
Basti Ortiz

Keep up the good work!

Collapse
 
tabuz profile image
Trebuh

Thanks for introducing me to this pattern. I've learned something here.

Collapse
 
iksdatoo profile image
Ilyas Karim

Good job

Collapse
 
juanlanus profile image
Juan Lanus

This may be the European way, with reasoning explanations instead of only code examples from where one is supposed to extract the gist of it.
Here it's clearly exposed.

Good!

Collapse
 
kirankiran480 profile image
GUDLA VENKATA SANTHOSH KIRAN

how to destroy a created singleton instance

Collapse
 
tomekbuszewski profile image
Tomek Buszewski

Hello Gudla,

You don't. Singleton, by design, is a single instance entity, so destroying it in one place would affect all the code that uses it. If you need destructible instances, don't use singletons.

Collapse
 
bgrand_ch profile image
Benjamin Grand • Edited

Thanks 😊 Your code example is very useful and clear.

Collapse
 
jochemstoel profile image
Jochem Stoel

You should stop using the word class in your class name. It is redundant to use class twice. It is not a class either, once instantiated it is an instance. Just call it class Singleton.

Collapse
 
tomekbuszewski profile image
Tomek Buszewski

Using the name is purely demonstrational, but I'll keep in mind to omit it next time.