JS Machine Coding Questions — Implementations You Must Know
Debounce
- Wait until calls stop for wait ms, then run once — classic for search-as-you-type and resize.
- Key insight: Each new call clears the pending setTimeout and schedules a fresh one.
- Trailing (default) fires after the burst; leading fires on the first call in a burst.
- Gotcha: Always expose .cancel() so callers can clear the timer on unmount.
- Gotcha: production libraries (Lodash) also support maxWait.
1// Trailing only
2function debounce(fn, wait) {
3 let timeoutId;
4 function debounced(...args) {
5 clearTimeout(timeoutId);
6 timeoutId = setTimeout(() => fn.apply(this, args), wait);
7 }
8 debounced.cancel = () => clearTimeout(timeoutId);
9 return debounced;
10}
11
12// Leading + trailing
13function debounce(fn, wait, { leading = false, trailing = true } = {}) {
14 let timeoutId;
15 return function (...args) {
16 const pending = timeoutId != null;
17 clearTimeout(timeoutId);
18 if (leading && !pending) fn.apply(this, args);
19 timeoutId = setTimeout(() => {
20 timeoutId = null;
21 if (trailing && (pending || !leading)) fn.apply(this, args);
22 }, wait);
23 };
24}