Implement Debounce
Wrap a function so it only fires after a quiet gap — every new call resets the clock, so a burst of activity collapses into one invocation once things settle.
The problem
Write `debounce(func, wait)` that returns a debounced version of `func`. Each call schedules `func` to run after `wait` milliseconds, but any call that arrives before the delay elapses cancels the pending run and restarts the timer.
The upshot: fire the wrapper ten times in quick succession and `func` runs exactly once, `wait` ms after the last call. It's the standard tool for taming high-frequency events like keystrokes, resize, and scroll.
The approach
A closure holds a single `timer` id that persists across calls to the returned function — that shared, mutable handle is the whole mechanism. Each invocation first does `clearTimeout(timer)` to cancel whatever was pending, then schedules a fresh `setTimeout`.
Because every call clears the previous timeout before setting a new one, only the final call in a burst survives to actually fire — the earlier ones are cancelled mid-flight. The trailing `func(...args)` runs with the most recent arguments, since each call overwrites what the pending timer would have used.
Honest caveat about this version: the arrow function doesn't rebind `this`, so it captures the enclosing `this` rather than the caller's. A fully spec-faithful debounce uses a regular `function` and `func.apply(this, args)` so it works as a method. For plain standalone functions, this implementation is fine.
The solution
/**
* @param {(...args: Array<unknown>) => unknown} func
* @param {number} wait
* @returns {(...args: Array<unknown>) => void}
*/
export default function debounce(func, wait) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
func(...args);
}, wait);
};
}Time O(1)Space O(1)