Debounce: wait until the user stops doing something, then fire once. Throttle: fire at most once every N milliseconds, no matter how often the event happens.
Click the button rapidly, then stop. Watch how the three timelines respond differently. Raw fires every time. Throttled fires at most once per 300ms. Debounced waits until you stop.
The “edge” is which end of the quiet period triggers the handler. Most debounce implementations default to trailing. Most throttle implementations default to leading.
Trailing edge
fires after silence
Leading edge
fires immediately
debounce
function debounce(fn, ms) {let timeoutreturn (...args) => {clearTimeout(timeout)timeout = setTimeout(() => fn(...args), ms)}}
throttle
function throttle(fn, ms) {let last = 0return (...args) => {const now = Date.now()if (now - last >= ms) {last = nowfn(...args)}}}
O(1) per call, O(1) space