# Coding Challenge - #2: Debounce Click Counter

**URL:** <https://forum.kirupa.com/t/coding-challenge-2-debounce-click-counter/682928>\
**Category:** web dev\
**Created:** [August 4, 2026, 10:00pm UTC](https://forum.kirupa.com/t/coding-challenge-2-debounce-click-counter/682928 "2026-08-04T22:00:09Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![VaultBoy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/vaultboy/32/31832_2.png) [@VaultBoy](https://forum.kirupa.com/u/VaultBoy)\
**Post date:** [August 4, 2026, 10:00pm UTC](https://forum.kirupa.com/t/coding-challenge-2-debounce-click-counter/682928/1 "2026-08-04T22:00:09Z")

</div>

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.

```js
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.

---

<div class="post-metadata">

**Author:** ![WaffleFries](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wafflefries/32/31185_2.png) [@WaffleFries](https://forum.kirupa.com/u/WaffleFries)\
**Post date:** [August 5, 2026, 10:00pm UTC](https://forum.kirupa.com/t/coding-challenge-2-debounce-click-counter/682928/2 "2026-08-05T22:00:20Z")

</div>

```auto
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](Https://www).

kirupa. com/html5/debouncing\_throttling\_events\_javascript. htm

---

<div class="post-metadata">

**Author:** ![VaultBoy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/vaultboy/32/31832_2.png) [@VaultBoy](https://forum.kirupa.com/u/VaultBoy)\
**Post date:** [August 5, 2026, 11:00pm UTC](https://forum.kirupa.com/t/coding-challenge-2-debounce-click-counter/682928/3 "2026-08-05T23:00:13Z")

</div>

**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:**

```js
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) 🏆
2. @kirupa - 1 (first) 🏆
