前端真麻烦,概念真多,今天碰到了函数节流(Throttle)和函数防抖(Debounce)
前面我在 WordPress 后台集成了标签选择器(tag-input)和多选选择器(mu-select),其中「Tag-input」有个功能是:按退格键(Backspace)不仅可以删除输入的文字,也可以删除前面的标签(为了防止误删,需要快速按两次)。
「为了防止误删,需要快速按两次」这个是怎么实现的,我搜索了一圈和问了 DeepSeek,原来有个牛逼的技术叫做 Debounce,中文翻译成函数防抖,和它一起出现的还有个概念叫做 Throttle,中文翻译是函数节流。
于是各种搜索和 DeepSeek 问,把这两个概念理解的七七七八八,简单整理一篇文章,防止以后快速能用上。先来 DeepSeek 最这个的一句话总结:
函数节流(Throttle)和函数防抖(Debounce)是控制函数执行频率的两种常用技术,它们的核心目标都是优化高频事件触发时的性能,但实现方式和适用场景有所不同。
函数节流(Throttle)
函数节流的核心是固定时间间隔内只执行一次函数,即使事件被频繁触发,函数也会按照设定的时间间隔规律性执行。

实现原理:
- 记录上一次执行的时间戳,每次触发时判断当前时间与上次执行的时间差。
- 如果时间差大于等于设定的间隔,则执行函数并更新上次执行时间;否则忽略本次触发。
应用场景:
- 高频事件需定期响应:如滚动(
scroll
)、窗口调整(resize
)、鼠标移动(mousemove
)。 - 防止重复操作:如游戏中的射击按钮(限制点击频率)、表单提交按钮(避免重复提交)。
代码示例:
这里仅做演示,一般 Lodash 和 UnderScore 已经带了 throttle
函数。
function throttle(func, wait){
let lastTime = 0;
return function(...args){
const now = Date.now();
if(now - lastTime >= wait){
func.apply(this, args);
lastTime = now;
}
};
}
函数防抖(Debounce)
函数防抖的核心是等待事件停止触发后,延迟执行函数。如果事件在等待期间被再次触发,则重新计时。

实现原理:
- 每次触发时清除之前的定时器,并重新设置一个定时器。
- 只有在事件停止触发超过设定时间后,函数才会执行。
应用场景:
- 输入结束后执行:如搜索框联想建议(用户停止输入后发送请求)。
- 避免重复触发:如窗口调整结束后的布局计算(
resize
结束)、表单提交按钮防抖(防止多次提交)。
代码示例:
这里仅做演示,一般 Lodash 和 UnderScore 已经带了 debounce
函数。
function debounce(func, wait, immediate=false){
let timeout;
return function(...args){
const context = this;
const later = ()=> {
timeout = null;
if(!immediate){
func.apply(context, args);
}
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow){
func.apply(context, args);
}
};
}
核心区别
特性 | 节流(Throttle) | 防抖(Debounce) |
---|---|---|
执行时机 | 固定间隔执行一次 | 事件停止触发后延迟执行 |
适用场景 | 需定期响应的连续事件(如滚动、拖拽) | 只需最终结果的场景(如输入验证、搜索) |
高频触发结果 | 规律性执行(如每 100ms 一次) | 仅执行最后一次触发 |
如何选择?
- 需要即时反馈:用节流(如拖拽、滚动时更新元素位置),结合
leading
和trailing
选项 - 只需最终结果:用防抖(如搜索建议、输入验证),结合
immediate
选项。
通过合理使用这两种技术,可以有效优化性能并提升用户体验。