The Singleton pattern ensures a class has only one instance and provides a global point of access to it. In JavaScript, it's commonly used for configuration managers, logging services, caches, and state stores.
+---------------+
| Application |
+---------------+ getInstance()
| Component A --+-------------------+
| Component B --+-------------------+
| Component C --+-------------------+
+---------------+
▲
| single shared object
+-------------------+
| SINGLETON 🔑 | <-- exactly one, globally accessible
+-------------------+
Guarantee : only one object exists, and it’s easily accessible across the codebase.
| Use‑Case | Why Singleton? |
|---|---|
| Config / Feature Flags | Global access in any component. |
| Analytics / Logging Client | Maintain one WebSocket or batch queue. |
| Theme Manager | One source of truth for dark‑/light mode state. |
| Event Bus | Pub/Sub across micro‑frontends. |
// analytics.js class Analytics { log(event, data) { /* send to server */ } } export const analytics = new Analytics(); // already a singleton
🤔 Why it works: ES modules are singletons by spec —imported once, cached forever.
class ThemeStore { static #instance; constructor() { if (ThemeStore.#instance) return ThemeStore.#instance; // enforce single this.mode = "light"; ThemeStore.#instance = this; } toggle() { this.mode = this.mode === "light" ? "dark" : "light"; } } export default ThemeStore; // `new ThemeStore()` anywhere -> same object
let _instance; export function getLogger() { if (!_instance) _instance = createRealLogger(); return _instance; } // In tests: override _instance = createMockLogger();
In a singleton design pattern, only one object is created for each interface (class or function), and the same object is returned every time the function or class is invoked.
This pattern is especially useful in scenarios where only one object is needed to coordinate actions across the system — such as a notification manager, database connection, or event dispatcher.
const Singleton = (function () { let instance; function createInstance() { const object = new Object("I am the instance"); return object; } return { getInstance: function () { if (!instance) { instance = createInstance(); } return instance; } }; })(); const object1 = Singleton.getInstance(); const object2 = Singleton.getInstance(); console.log(object1 === object2); // true
✅ This pattern uses a private variable (
<span>instance</span>) enclosed within an IIFE (Immediately Invoked Function Expression) to ensure that the<span>createInstance</span>function is only called once.
| ✅ Advantages | ⚠️ Drawbacks |
|---|---|
| Easy shared state | Hidden global -> hard to trace dependencies |
| Resource efficiency (one socket) | Unit tests need mocking / reset state |
| Simplifies configuration | Tight coupling: swapping impl is harder |
| Controlled access (centralised) | Cannot subclass easily (sealed) |
Rule of Thumb: If the object holds stateless functions , prefer pure modules. Use Singleton only for stateful shared resources .
getInstance() function and allow tests to inject a mock before first call.jest.mock('./analytics', () => ({ analytics: mockObj })).resetForTests() exported only in non‑prod builds to clear internal state.| Question | Key Ideas |
|---|---|
| "How does ES module system enable singletons?" | Module executed once, live bindings cached -> every import gets same exports. |
| "How would you make a singleton thread‑safe?" | JS main thread is single; in workers use atomics / message passing. |
| "Why can Singleton hinder SSR?" | State leaks between user requests; solve via factory per request. |
| "Alternatives to Singleton?" | Dependency Injection containers, passing props, context providers. |
| Anti‑Pattern | Symptom | Fix |
|---|---|---|
| God Singleton | Holds too many responsibilities | Split by bounded context |
| Hidden Imports | File deep‑importing singleton silently | Explicit injection via props / DI |
| Stateful Tests Bleed | One test contaminates another | Provide reset helper or fresh module registry per test |
Master these nuances and you'll nail Singleton questions with confidence! 🚀
Test your understanding with 3 quick questions