在JavaScript 中的防抖(debounce)和节流(throttle),这两个概念在前端开发中非常常见,尤其是在处理频繁触发的事件(如窗口调整、滚动、输入等)时,用来优化性能。
1. 防抖(Debounce)
概念
防抖是指在事件被触发后,延迟一段时间才执行回调函数。如果在这段时间内事件再次被触发,则重新开始计时,只有当指定的延迟时间过去且没有新的触发时,回调函数才会执行。
通俗理解
想象你在电梯里等人,门快要关上的时候又有人进来,你会重新等待一段时间。如果一直有人进来,你就一直等,直到没人再进来,等待时间到了,电梯门才会关上。防抖就是这种“等一等,最后一次触发后再执行”的逻辑。
应用场景
- 输入框实时搜索:用户输入时不立刻发送请求,而是等用户停下来(比如停止输入500ms)再发送。
- 窗口resize事件:避免频繁计算,只有调整窗口大小停止后再执行逻辑。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function debounce(fn, delay) { let timer = null; return function (...args) { clearTimeout(timer); // 如果有新的触发,清除之前的定时器 timer = setTimeout(() => { fn.apply(this, args); // 延迟执行 }, delay); }; } // 示例:用户输入停止500ms后打印 const logInput = debounce((value) => { console.log("输入值:", value); }, 500); input.addEventListener("input", (e) => logInput(e.target.value)); |
2. 节流(Throttle)
概念
节流是指在一段时间内,无论事件触发多少次,回调函数只会在固定的时间间隔内执行一次。也就是说,它限制了执行的频率。
通俗理解
想象你在玩射击游戏,枪有冷却时间,哪怕你疯狂按射击键,子弹也只能每隔一段时间发射一次。节流就是这种“控制频率,按固定间隔执行”的逻辑。
应用场景
- 滚动事件:监听页面滚动时,每隔一段时间检查一次位置,而不是每次滚动都触发。
- 按钮点击:防止用户短时间内多次点击提交表单。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function throttle(fn, interval) { let lastTime = 0; return function (...args) { const now = Date.now(); if (now - lastTime >= interval) { // 检查时间间隔 fn.apply(this, args); lastTime = now; // 更新上一次执行时间 } }; } // 示例:每500ms打印一次滚动位置 const logScroll = throttle(() => { console.log("滚动位置:", window.scrollY); }, 500); window.addEventListener("scroll", logScroll); |
防抖 vs 节流
特性 | 防抖 (Debounce) | 节流 (Throttle) |
---|---|---|
执行时机 | 事件停止触发后延迟执行一次 | 事件触发期间按固定间隔执行 |
核心目的 | 减少不必要的执行,只关注最后一次 | 控制执行频率,均匀分配执行 |
典型场景 | 输入校验、搜索建议 | 滚动加载、按钮防连点 |
总结
- 防抖适合需要“等事情平静下来再处理”的场景,强调最后一次触发的执行。
- 节流适合需要“持续但有节奏地处理”的场景,强调执行的频率控制。