Design Patterns
A design pattern is just a recognised, named solution to a recurring problem — none of the three covered here are new syntax; they're specific ways of combining things already learned (closures, callbacks, timers) to solve specific, common problems cleanly.
The Module Pattern — Closures as Encapsulation
This is exactly Intermediate Chapter 2's createBankAccount private-state pattern, with one addition: an IIFE (Immediately Invoked Function Expression) — the surrounding (function() { ... })() — runs the function the instant it's defined, so CounterModule ends up holding the returned object directly, not the function itself. Before native ES modules (Chapter 1) existed, this was the standard way to create a private, self-contained unit of code.
import/export (Chapter 1) has mostly replaced this pattern's original purpose — but the underlying technique (closures hiding private state, exposing only a deliberate public interface) still shows up constantly inside individual files, classes, and libraries, regardless of module system.
The Observer Pattern — One-to-Many Notifications
The observer pattern lets multiple unrelated pieces of code (observers) react to something happening, without the thing that happened needing to know who's listening or how many there are. addEventListener (Fundamentals Chapter 8) is observer pattern, built into the browser — EventEmitter here is the same idea, generalized beyond DOM events to any custom event name.
Debounce — Wait Until Activity Stops
debounce wraps a function so it only actually runs once activity has genuinely stopped for delay milliseconds — each new call cancels the previous pending timer and starts a fresh one. This is the standard fix for Fundamentals Chapter 9's "input" event firing on every keystroke when a search box should really only query once typing pauses.
Throttle — Allow at Most Once Every X Milliseconds
throttle guarantees the wrapped function runs AT MOST once per limit milliseconds, no matter how many times it's called in that window — unlike debounce, the first call goes through immediately, and the function fires regularly during sustained activity rather than waiting for it to stop entirely. scroll events fire dozens of times per second; throttling keeps expensive work (logging, layout calculations) from running that often.
| Pattern | Problem it solves | Built from |
|---|---|---|
| Module pattern | Private state, public interface | Closures + IIFE |
| Observer | Many listeners reacting to one event, decoupled | Arrays of callbacks + forEach |
| Debounce | "Run once activity stops" (search-as-you-type) | setTimeout + clearTimeout |
| Throttle | "Run at most once per interval" (scroll/resize) | setTimeout + a boolean flag |
Coding Challenges
Using the module pattern (IIFE returning an object), build a TodoModule with private state (an array) and a public interface of addTodo(text) and getAll(). Add 3 todos and log the result of getAll(), then confirm TodoModule.todos is undefined.
📄 View solutionUsing the EventEmitter class from this chapter, create an instance and register two separate listeners for an "orderPlaced" event — one logging a confirmation message, one logging that an email should be sent. Emit the event once with an order ID and confirm both listeners run.
📄 View solutionUsing the debounce function from this chapter, wrap a function that logs "Saving..." with a 500ms delay. Call the debounced version 5 times in quick succession (e.g. in a loop with no delay between calls) and explain in a comment why "Saving..." only logs once.
📄 View solutionChapter 4 Quick Reference
- Module pattern — IIFE + closure, returning a deliberate public interface, hiding private state
- IIFE: (function() { ... })() — runs immediately, only what it returns survives
- Observer pattern — register listeners, emit events; addEventListener is this pattern, built-in
- Debounce — runs once, after activity stops for a set delay (search-as-you-type)
- Throttle — runs at most once per interval, during continuous activity (scroll/resize)
- None of these are new syntax — all three combine closures, timers, and callbacks already covered
- Next chapter: working with APIs — pagination, rate limits, caching strategies