On this page · sections
JavaScript Patterns, FP & Architecture
Can you pick a pattern because it matches the change you expect — not because it has a name?
Design patterns in JavaScript are small: Observer, Strategy, Module, Command. Functional style is the other half: pure functions, immutability, composition.
Coding pages implement EventEmitter, pipe, and LRU. This page is when to reach for them.
Questions
Patterns
Functional style
Senior-Level Follow-ups
Patterns
1. Observer vs Pub/Sub
Why This Matters
React subscribe, DOM events, and Redux are variants of “notify later.”
Problem
What is the difference between Observer and Pub/Sub?
Example
Observer: the subject holds a list of observers. Direct, typed, easy to unsubscribe.
store.subscribe(fn)
button.onclick = fnPub/Sub: a broker in the middle. Publishers do not know subscribers. Flexible, easier to leak, harder to type.
bus.emit("user:login", payload)EventEmitter is Observer with string event names — EventEmitter.
Always snapshot listeners before emit. Always unsubscribe.
Interview Answer
“Observer is a direct list of callbacks. Pub/Sub adds a broker and event names. I use Observer for a store; I use a bus only when modules must not import each other. Either way, emit iterates a snapshot.”
2. Strategy and Composition
Why This Matters
if (type === "csv") exportCsv() grows into an unmaintainable switch.
Problem
How do you swap algorithms without rewriting the caller?
Example
const exporters = {
csv: exportCsv,
json: exportJson,
};
function exportFile(format, data) {
const fn = exporters[format];
if (!fn) throw new Error(`Unknown format: ${format}`);
return fn(data);
}That is Strategy: the behavior is a value.
React composition (children, render props, hooks) is the UI version. Prefer passing a function or component over a deep class hierarchy.
Interview Answer
“Strategy makes the algorithm a parameter. I keep a map of functions or pass a callback. I use inheritance only when I have a real subtype, not to vary one method.”
Functional style
3. Pure Functions and Immutability
Why This Matters
Pure functions are easy to test and to replay. They are not a religion — I/O has to live somewhere.
Problem
What is purity, and why copy instead of mutate shared state?
Example
function add(a, b) {
return a + b;
}
function addTag(item, tag) {
return { ...item, tags: [...item.tags, tag] };
}Same inputs → same output, no observable side effects.
HOFs (map, filter, memoize) take or return functions. They are useful when the abstraction is real.
Immutability is shallow unless you clone. Shared nested refs still mutate — Objects, Arrays & Descriptors.
pipe / curry implementations: Pipe, Compose & Curry.
Interview Answer
“A pure function depends only on its inputs and does not mutate shared state. I keep domain logic pure and push I/O to the edges. I copy on write for shared UI state, knowing spread is shallow.”
4. The Module Pattern
Problem
How did JS encapsulate before ESM, and what still applies?
Example
const api = (function () {
let token = null;
return {
setToken(value) {
token = value;
},
getToken() {
return token;
},
};
})();IIFE + closure = private state. ESM let at module scope is the same idea with better syntax.
Singletons at module scope are process-wide on the server. Do not store request data there.
Interview Answer
“The module pattern is a closure that returns a public API. ESM modules are the language version. I still use factories when I need multiple instances or per-request state.”
Senior-Level Follow-ups
5. Flags vs a State Machine
isLoading && isSuccessis an impossible product state.
If states are mutually exclusive, use one value and a transition table — not a handful of booleans.
Independent flags (isDarkMode, isModalOpen) can stay booleans.
6. Command vs Snapshot for Undo
Command: store execute / undo. Cheap, needs a correct inverse.
Snapshot: store the whole state. Simple, heavy.
Editors often mix: snapshot every N commands. New user actions clear redo.
7. When Patterns Become Noise
A 40-line feature does not need Factory + Abstract Factory + Visitor.
Name the problem: notification, swappable algorithm, reversible action, exclusive UI state.
If the code is clearer as a function, skip the class diagram.
Final Interview Strategy
1. Observer for stores; bus only for decoupling
2. Snapshot emit; unsubscribe
3. Strategy = behavior as data
4. Pure core, I/O at edges
5. Module/factory for privacy and instances
6. One state string for exclusive workflows
7. Don't pattern-match for sportSenior-level signal: Pick the pattern from the invariant you need (notify, swap, reverse, exclusive state). Then mention the production edge: leaks, SSR singletons, or impossible flags.