函数防抖与节流均可优化高频事件性能;防抖通过延迟执行并重置定时器,确保连续触发时只执行最后一次或首次;节流则通过时间戳或定时器控制函数固定频率执行,保证周期性响应;两者分别适用于搜索输入、按钮点击与滚动监听、窗口缩放等场景。

在处理高频触发事件时,比如窗口滚动、调整大小或输入框输入,直接执行回调会导致性能问题。函数节流和防抖是两种常用的优化手段,控制函数执行频率,提升页面响应速度与用户体验。
函数防抖(Debounce)
防抖的思路是:当事件被触发后,延迟一段时间执行回调,如果在这段时间内再次触发该事件,则重新计时。
适用于搜索建议、按钮重复点击等场景,只关心“最后一次操作”。
实现方式:- 使用 setTimeout 缓存定时器
- 每次触发时清除旧定时器,重新设置
- 延迟结束后执行目标函数
基础防抖实现:
function debounce(func, wait) {let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
若需立即执行首次调用(leading edge),可加入 immediate 参数控制:
function debounce(func, wait, immediate) {let timeout;
return function(...args) {
const context = this;
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(() => {
timeout = null;
if (!immediate) func.apply(context, args);
}, wait);
if (callNow) func.apply(context, args);
};
}
函数节流(Throttle)
节流的逻辑是:规定一个单位时间,在这个时间内最多只执行一次函数。无论触发多少次,都按固定节奏执行。
适合用于 scroll、resize、mousemove 等持续触发但只需周期性响应的场景。
- 记录上一次函数执行的时间戳
- 每次触发时判断当前时间是否超过设定间隔
- 满足条件则执行并更新时间戳
基于时间戳的节流实现:
function throttle(func, wait) {let previous = 0;
return function(...args) {
const now = Date.now();
const context = this;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
};
}
也可以使用定时器方式实现,更灵活地控制首尾执行时机:
function throttle(func, wait) {let timeout;
return function(...args) {
const context = this;
if (!timeout) {
timeout = setTimeout(() => {
func.apply(context, args);
timeout = null;
}, wait);
}
};
}
防抖与节流的核心区别
理解两者差异有助于正确选择使用场景:
- 防抖:频繁触发下只执行最后一次(或第一次),中间的都被取消
- 节流:保证在指定时间间隔内至少执行一次,形成稳定频率
举个例子:用户连续快速滚动页面
- 用防抖,可能在整个滚动结束才执行一次处理
- 用节流,每100ms执行一次,能及时响应又不至于太频繁
基本上就这些,根据业务需求选择合适方案即可。










