Coding Challenges and Patterns
Frontend rounds often ask you to build small utilities from scratch, such as debounce, Promise.all, deepClone or an event emitter, and then probe the edge cases. Know the contract of each, the bugs reviewers look for, and the cost of each approach.
Key points
- 1
Debounce waits for a pause and runs once with the latest arguments; throttle runs at most once per window. Both must forward
thisand arguments: return a regularfunctionand callfn.apply(this, args). - 2
Promise.all must keep input order (
out[i] = vplus a separate counter), resolve[]immediately, wrap plain values withPromise.resolve, and accept any iterable (Array.from(items)). - 3
Memoize keys matter: plain objects stringify to
"[object Object]"andJSON.stringifymergesundefined,nullandNaN. Use aMaporWeakMapper argument, or a deliberate key function. - 4
Deep clone with cycles: register the clone in a
WeakMapbefore recursing. Copying own keys losesDate,Map,Setand prototypes;structuredClonehandles cycles and built-ins but rejects functions. - 5
An event emitter iterates over a copy of its listener list, and
onceremoves its wrapper before calling the listener while remembering the original foroff. - 6
In a
Map-based LRU cache, bothgetandputmust delete and re-insert the key; the least recently used key ismap.keys().next().value. - 7
Polyfills follow the spec:
bindmust supportnew,reduceskips holes and throws on an empty array with no initial value, andinstanceofreturns false for primitives.
Common traps
return fn()insidetrydoes not catch an async rejection; usereturn await fn().A concurrency pool that never removes settled promises from its race array stops limiting after the first completion.
Curry by
fn.lengthbreaks with default or rest parameters, because they lower the reported arity.
Test yourself on Coding Challenges and Patterns
Ten questions, with the answer and explanation after each one.