What is a Singleton Pattern in JavaScript?

A singleton lets you create only one instance of a class that you will use globally throughout your application.

With the help of an external variable, instance you will store the instance in it for checking. This will prevent anyone from creating a 2nd instance of this class.

let instance
let counter = 0

class Counter {
  constructor() {
    if (instance) {
      throw new Error("you can only create one instance")
    }
    instance = this
  }

  getInstance() {
    return this
  }

  getCount() {
    return counter
  }

  increment() {
    return ++counter
  }

  decrement() {
    return --counter
  }
}

Instead of exporting this class, you will export the singleton instance, since the whole point of this pattern is to have just one copy of an object:

const singletonCounter = new Counter()

export default singletonCounter

JavaScript lets you mutate (modify) the created object by adding new properties or changing methods, which is not what you want:

// consumer.js

singletonCounter.increment = () => console.log("Hello I am a singleton")
singletonCounter.name = "My Singleton"

That's why, before you export this object, it's a good idea to freeze this object using Object.freeze method.

const singletonCounter = Object.freeze(new Counter())

export default singletonCounter

Object.freeze prevents you from modifying any object by adding/editing properties or methods.

Now the following will throw an error:

singletonCounter.increment = () => console.log("Hello I am a singleton")
singletonCounter.name = "My Singleton"