Debounce and throttle are techniques to control how often a function runs in response to rapid events. Debounce waits for a pause; throttle enforces a maximum rate.
DEBOUNCE delays invoking a function until a specified quiet period has elapsed since the last call — every new call resets the timer. It is ideal for events that fire in bursts where you only care about the final state: search-as-you-type, window resize, or auto-save. THROTTLE guarantees a function runs at most once per interval no matter how many times it is triggered — ideal for continuous events where you want steady sampling: scroll handlers, mousemove, or rate-limiting API calls. Both are implemented with closures and timers. The mental model: debounce = 'wait until they stop'; throttle = 'run at a fixed cadence'.
A search box that calls an API on every keystroke would fire dozens of requests; debouncing the handler by 300ms means the API is called once after the user stops typing. A scroll-based lazy-loader is throttled to run at most every 200ms so it stays smooth.
Implement a debounce(fn, delay) function and explain when you would use throttle instead.