Question presented to candidate: "Implement a debounce function from scratch. Walk me through why it works, then show me it actually collapsing a burst of rapid calls into one."
What a strong answer should cover:
- A closure holding a single timer id across calls.
- Every call clears the previous pending timer, then starts a brand-new one — this is the entire mechanism.
- The wrapped function only actually runs once no new call has arrived within the delay window, and it runs with the arguments from the LAST call, not the first.
- Correct
thishandling if the debounced function needs to be used as a method (use a regular function for the wrapper andfn.apply(this, args), not an arrow function, if the caller relies on dynamicthis). - Real verification: proving with actual timestamps that a rapid burst produces exactly one effect call, not an assumption from reading the code.
Clarifying questions expected:
- "Should the debounced function support being called as an object method (i.e. does
thisneed to work), or is a plain top-level function enough?" - "Do you want a
.cancel()method as part of this, or is that a separate follow-up?" (confirms scope — the advanced .cancel() variant is a distinct question in this bank)
Code / implementation expected: Yes — a full working debounce implementation, executed with a rapid-fire burst and real observed timestamps proving only the last call's effect fires.