DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
← From Beginner to Expert in Fundamentals of Frontend
  • Scope & Closures
  • Asynchronous JavaScript
  • DOM Manipulation
  • ES6+ to 2026
  • Execution Context & Call Stack
  • Hoisting: var, let, const & Functions
  • Data Types & Type Coercion
  • Prototypes & the this Keyword
  • The Event Loop Deep Dive
  • Higher-Order Functions, Currying & Functional Patterns
  • Callbacks, Promises & Async/Await
  • Event Delegation & DOM Optimization
  • Destructuring, Spread/Rest & Modern Syntax
  • ES Modules & the Fetch API
  • Memory Management & Garbage Collection
  • Debouncing, Throttling & Performance Patterns
  • Design Patterns in JavaScript
  • Proxies, Reflect & Symbols
  • JavaScript Optimizations & Best Practices
  • JavaScript Interview Questions (30 MCQs)
← From Beginner to Expert in Fundamentals of Frontend

Design Patterns in JavaScript

22 min read
SingletonObserverFactoryModuleProxyIteratorGeneratorsDesign Patterns

Essential JavaScript Design Patterns

1. Singleton Pattern

Ensures a class has only ONE instance.

class Database {
  static #instance = null;
  
  constructor(connectionString) {
    if (Database.#instance) return Database.#instance;
    this.connection = connectionString;
    Database.#instance = this;
  }
  
  static getInstance(conn) {
    if (!Database.#instance) {
      Database.#instance = new Database(conn);
    }
    return Database.#instance;
  }
}

const db1 = Database.getInstance("postgres://...");
const db2 = Database.getInstance("mysql://...");
db1 === db2; // true (same instance, first connection wins)

2. Observer Pattern (Pub/Sub)

class EventEmitter {
  #listeners = new Map();

  on(event, callback) {
    if (!this.#listeners.has(event)) {
      this.#listeners.set(event, new Set());
    }
    this.#listeners.get(event).add(callback);
    return () => this.off(event, callback); // Return unsubscribe function
  }

  off(event, callback) {
    this.#listeners.get(event)?.delete(callback);
  }

  emit(event, ...args) {
    this.#listeners.get(event)?.forEach(cb => cb(...args));
  }
}

const bus = new EventEmitter();
const unsub = bus.on("userLogin", (user) => console.log(`Welcome ${user}`));
bus.emit("userLogin", "Alice"); // "Welcome Alice"
unsub(); // Clean up

3. Factory Pattern

class NotificationFactory {
  static create(type, message) {
    switch (type) {
      case "email": return new EmailNotification(message);
      case "sms": return new SMSNotification(message);
      case "push": return new PushNotification(message);
      default: throw new Error(`Unknown type: ${type}`);
    }
  }
}

const notification = NotificationFactory.create("email", "Hello!");
notification.send();

4. Module Pattern (with Closures)

const Counter = (() => {
  let count = 0; // Private

  return {
    increment: () => ++count,
    decrement: () => --count,
    getCount: () => count,
  };
})();

Counter.increment(); // 1
Counter.getCount();   // 1
Counter.count;        // undefined (private!)

5. Proxy Pattern

const handler = {
  get(target, prop) {
    console.log(`Accessing ${prop}`);
    return prop in target ? target[prop] : `Property ${prop} not found`;
  },
  set(target, prop, value) {
    if (prop === "age" && typeof value !== "number") {
      throw new TypeError("Age must be a number");
    }
    target[prop] = value;
    return true;
  }
};

const user = new Proxy({}, handler);
user.name = "Alice";
user.age = "thirty"; // TypeError: Age must be a number

6. Iterator Pattern (Generators)

function* range(start, end, step = 1) {
  for (let i = start; i < end; i += step) {
    yield i;
  }
}

for (const num of range(0, 10, 2)) {
  console.log(num); // 0, 2, 4, 6, 8
}

// Infinite sequence
function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();
fib.next().value; // 0
fib.next().value; // 1
fib.next().value; // 1
fib.next().value; // 2

Pattern Selection Guide

PatternUse WhenReal-World Example
SingletonOne instance globallyDatabase connection, Logger
ObserverEvent-driven communicationRedux store, DOM events
FactoryCreating objects by typeUI component factories
ModuleEncapsulation & privacyAPI clients, utilities
ProxyValidation, logging, cachingVue.js reactivity, ORMs
IteratorLazy evaluation, sequencesPagination, data streams

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.