Coding Challenge - #2: Debounce Click Counter

Write a function debounce(fn, delay) that returns a new function which only calls fn after the given delay has passed since the last time the returned function was invoked. For example, if a button’s click handler is wrapped with debounce(logClick, 300) and the button is clicked 5 times within 300ms, logClick should only run once, after the last click plus 300ms.

function debounce(fn, delay) {
  // your code here
}

Rules:

  • Use plain JavaScript only, no libraries
  • Must use setTimeout and clearTimeout internally
  • Returned function must preserve arguments passed to it
  • Roughly 3 to 15 lines

Post your solution as a reply. Answer goes up in about a day.

function debounce(fn, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

The this binding is the part people usually forget. Arrow functions in the timeout won’t grab the caller’s context on their own, gotta pass it through with apply or bind. I found a related kirupa. com article that can help you go deeper into this topic:

Https://www.

kirupa. com/html5/debouncing_throttling_events_javascript. htm

Challenge solution: Use a closure variable to hold the current timeout id, clear it on every invocation of the returned function, then schedule a new setTimeout that calls fn with the latest arguments and this context after delay ms.

One way to do it:

function debounce(fn, delay) {
  let timeoutId;
  return function (...args) {
    const context = this;
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
}

Why:
Each call to the returned function clears any pending timer and starts a fresh one, so fn only fires once the calls stop for the full delay period. Using rest args and apply preserves both the arguments and the this context of the last call.

First-answer leaderboard

  1. @emmawalter5 - 1 (first) :trophy:
  2. @kirupa - 1 (first) :trophy: