防抖与节流(防抖与节流的区别和使用场景)
防抖(Debounce)和节流(Throttle)是两种常见的性能优化技术,用于控制函数在高频事件(如滚动、输入、点击等)中的执行频率。它们的本质区别在于对事件触发的处理逻辑不同:
1. 防抖(Debounce)
- 本质:
延迟执行,在事件被频繁触发时,只有最后一次触发后等待一定时间没有新触发,才会执行函数。 - 类似于“等待用户停止操作后再执行”。
- 如果事件持续触发,函数会一直被延迟,直到触发间隔超过设定的时间。
- 核心逻辑:
每次触发时重置计时器,重新开始等待。 - 典型场景:
- 搜索框输入(用户停止输入后再发送请求)。
- 窗口大小调整(调整结束后再计算布局)。
- 代码示例:
function debounce(fn, delay) {
let timer;
return function() {
clearTimeout(timer); // 重置计时器
timer = setTimeout(() => fn.apply(this, arguments), delay);
};
}
2. 节流(Throttle)
- 本质:
固定频率执行,在事件频繁触发时,函数按照设定的时间间隔周期性执行。 - 类似于“无论触发多快,每 X 毫秒只执行一次”。
- 即使事件持续触发,函数也会按固定节奏执行。
- 核心逻辑:
通过时间戳或标志位判断是否到达执行周期。 - 典型场景:
- 滚动事件(每隔一段时间计算位置)。
- 高频点击(如游戏射击按钮)。
- 代码示例(时间戳版):
function throttle(fn, delay) {
let lastTime = 0;
return function() {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, arguments);
lastTime = now;
}
};
}
关键区别总结
特性 | 防抖(Debounce) | 节流(Throttle) |
执行时机 | 最后一次触发后等待 delay 毫秒执行 | 每隔 delay 毫秒固定执行一次 |
重置延迟 | 每次触发都会重置计时器 | 按时间周期触发,不重置计时器 |
极端情况 | 如果持续触发,函数永远不执行 | 即使持续触发,也会按间隔执行 |
适用场景 | 关注结果(如输入停止后搜索) | 关注过程(如滚动时实时计算位置) |
直观比喻
- 防抖:电梯门等待最后一个人进入后关闭(如果一直有人进,门会一直不关)。
- 节流:地铁发车,每隔 5 分钟一班(不管多少人排队)。
根据实际需求选择合适的技术:需要减少执行次数但确保最终结果时用防抖,需要均匀分摊执行压力时用节流。