防抖和节流是前端开发中优化高频事件处理的两个技巧,就像给“过于活跃”的事件装上刹车,避免它们频繁触发导致的卡顿或资源浪费。
一、防抖(Debounce)——「等你说完我再干」
比喻:电梯关门。当有人进电梯时,门不会立即关闭,而是等待几秒(比如5秒)。如果在这5秒内又有人进来,计时器重置,直到5秒内无人进出,门才关闭。
作用:事件触发后,等待一段时间,如果期间没有再次触发,才执行函数。如果重复触发,则重新计时。
适用场景:
- 搜索框等用户停止输入再搜索)
- 窗口调整大小(停止调整后再计算布局)
- 防止按钮重复提交(点击后等一会儿再执行)
代码实现:
function debounce(func, delay) {
let timer;
return function() {
clearTimeout(timer); // 每次触发都重置计时器
timer = setTimeout(() => {
func.apply(this, arguments);
}, delay);
};
}
// 使用示例:输入框防抖
input.addEventListener('input', debounce(search, 500));
二、节流(Throttle)——「再急也得按节奏来」
比喻:水龙头节水器。无论你拧得多快,水流都会以固定频率(比如每秒一滴)流出,强行限制单位时间的流量。
作用:确保函数在指定时间间隔内只执行一次,无视期间的多次触发适用场景**:
- 滚动事件(每隔一段时间计算位置)
- 鼠标移动(降低mousemove事件频率)
- 游戏中的技能冷却(点击再快也只能按CD释放)
代码实现(时间戳版):
function throttle(func, delay) {
let lastTime = 0;
return function() {
const now = Date.now();
if (now - lastTime >= delay) {
func.apply(this, arguments);
lastTime = now;
}
};
}
// 使用示例:滚动节流
window.addEventListener('scroll', throttle(updatePosition, 200));
三、区别对比表
防抖(Debounce) | 节流(Throttle) | |
---|---|---|
核心 | 等事件停止后再执行 | 按固定节奏执行 |
效果 | 可能延迟执行 | 保证均匀执行 |
类比 | 电梯等人 | 水龙头滴水 |
场景 | 搜索建议、窗口调整 | 滚动加载、水龙头节水器 |
四、进阶技巧
- 防抖立即执行版:首次触发立即执行,后续等待停止后再触发(如提交按钮防止重复点击)。
- 节流尾部执行版:确保最后一次触发会被执行(如滚动结束后的回调)。
总结:
- 防抖是「等你冷静下来再做事」,适合结果型操作(如搜索)。
- 节流是「再急也得排队来」,适合过程型操作(如滚动)。