Katkat

Implement a debounce function

AppleSoftware Engineer · Technical Screen

Last updated

This problem tests your understanding of JavaScript closures, asynchronous timers, and the ability to maintain internal state across multiple function invocations.

Debounce Implementation

Implement a debounce(func, delay) function. The debounced function ensures that the original function func is only called after delay milliseconds have elapsed since the last time the debounced function was invoked. If the debounced function is called again before the timer expires, the previous timer should be cleared and a new timer should be started.

Requirements

  • The returned function must maintain the correct this context.
  • All arguments passed to the debounced function must be forwarded to the original func.

Function Signature

/**
 * @param {Function} func - The function to debounce.
 * @param {number} delay - Delay in milliseconds.
 * @return {Function} - The debounced version of the function.
 */
function debounce(func, delay) {
  // Implementation here
}

Examples

Example 1: Basic execution

const log = debounce(() => console.log('Hello!'), 1000);
log();
log();
// 'Hello!' will be printed exactly once, 1000ms after the second call.

Constraints

  • delay is a non-negative integer.
  • func may be an anonymous function or a method attached to an object.

Edge Cases

  • What happens if func returns a value? (Standard debouncing usually ignores this, but ensure the structure is clean).
  • Ensure consecutive rapid calls do not trigger multiple executions.

Hints

Hint 1

Use a closure to keep track of a persistent timer variable across multiple calls to the returned function.

Hint 2

Utilize `setTimeout` to schedule the execution and `clearTimeout` to cancel pending executions whenever the debounced function is invoked again.

Hint 3

Use `apply(this, arguments)` or the spread operator `(...args)` to ensure the original function receives its correct context and parameters.

Follow-up questions

  • How would you modify your implementation to support an 'immediate' flag, which triggers the function on the leading edge of the delay instead of the trailing edge?
  • If this were implemented in a browser environment, how might you optimize this to work with requestAnimationFrame instead of setTimeout?
  • How does your implementation differ from a 'throttle' function in terms of its behavior and use cases?