Debounce vs Throttle in JavaScript: Interview Implementations and Edge Cases
From-scratch implementations, leading and trailing calls, cancel, and the mistakes interviewers look for
ryan
Last Updated Oct 20, 2026

Debounce and throttle both limit how often a function runs, but they answer different questions. Interviewers usually ask you to implement one of them from scratch and then push on the edge cases, so it helps to know exactly where the two differ.
The one-line difference
- Debounce: run the function only after the calls have stopped for
waitms. Every new call resets the timer. - Throttle: run the function at most once every
waitms, no matter how many calls come in.
Typical use: debounce a search box (wait until the user stops typing), throttle a scroll or resize handler (keep updating, but not 60 times a second).
Debounce: the basic version
function debounce(fn, wait) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
};
}
Points interviewers check:
thisand arguments are preserved. Using a regularfunctionfor the returned wrapper andfn.apply(this, args)keeps the caller's context. An arrow function as the wrapper would lose it.- The timer lives in the closure, so every debounced function has its own timer.
- Only the last call's arguments are used. Earlier calls inside the window are dropped.
Debounce with leading edge and cancel
A common follow-up is "fire immediately on the first call, then ignore until things are quiet":
function debounce(fn, wait, { leading = false } = {}) {
let timer = null;
function debounced(...args) {
const callNow = leading && timer === null;
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
if (!leading) fn.apply(this, args);
}, wait);
if (callNow) fn.apply(this, args);
}
debounced.cancel = () => {
clearTimeout(timer);
timer = null;
};
return debounced;
}
cancel matters in React: call it in the effect cleanup so a pending call does not run after the component unmounts.
Throttle: timestamp version
function throttle(fn, wait) {
let last = 0;
return function (...args) {
const now = Date.now();
if (now - last >= wait) {
last = now;
fn.apply(this, args);
}
};
}
This fires on the leading edge and drops everything else in the window. The catch: the last call in a burst may never run, so the final scroll position can be missed.
Throttle with a trailing call
function throttle(fn, wait) {
let last = 0;
let timer = null;
let lastArgs = null;
let lastThis = null;
return function (...args) {
const now = Date.now();
const remaining = wait - (now - last);
lastArgs = args;
lastThis = this;
if (remaining <= 0) {
clearTimeout(timer);
timer = null;
last = now;
fn.apply(lastThis, lastArgs);
} else if (!timer) {
timer = setTimeout(() => {
last = Date.now();
timer = null;
fn.apply(lastThis, lastArgs);
}, remaining);
}
};
}
Now the first call runs right away and the latest arguments run once more at the end of the window, which is what you usually want for scroll and resize.
Quick comparison
| Debounce | Throttle | |
|---|---|---|
| Runs | after calls stop | at a steady max rate |
| Burst of 10 calls in 1s (wait 300ms) | 1 run, at the end | about 4 runs |
| Good for | search input, autosave, validation | scroll, resize, mousemove, drag |
Common mistakes
- Creating the debounced function inside a React render. Each render makes a new timer, so nothing is ever debounced. Wrap it in
useMemo/useRef, or build auseDebouncehook. - Forgetting to cancel on unmount, which causes state updates on unmounted components.
- Using
setIntervalfor throttle. It keeps running even when no events arrive. - Losing
thisby returning an arrow function wrapper.
If you can write the basic versions in a couple of minutes and explain the leading/trailing trade-off, you have covered what most frontend interviews ask about this topic.
Love this Blog? Share it Now!
Help others discover this resource
Learn next
Featured25 Top JavaScript Interview Questions for BeginnersEssential JS interview questions with clear answers for freshers and beginners.- Memory Leak in JavaScript: 4 Common Reasons
- Promise.all Polyfill — Interview Guide
- REST API Calls with Fetch (Machine Coding)
- 5 Rules to Master the this Keyword








