JavaScript 中节流(throttle)与防抖(debounce)原理及实现

作者:拾光时间:2026-10-28 12:01:07浏览:665

本文深入解析 JavaScript 中 throttle(函数节流)与 debounce(函数防抖)的核心概念与应用场景。通过对比鼠标移动、窗口缩放及文本输入等高频事件,阐明两种策略在控制执行频率与空闲时间上的差异,并提供完整的原生 JS 实现代码,帮助开发者优化页面性能。

函数节流(throttle)原理与应用

throttle

这里提到的 throttle 指的是函数节流。通俗来说,它是一个控制函数调用频率的机制,用于限制连续执行的时间间隔。其主要应用场景包括:

1. 鼠标移动时的 mousemove 事件; 2. DOM 元素动态定位涉及的 window 对象的 resize 和 scroll 事件。

有人形象地将上述事件比喻为机关枪的扫射,而 throttle 则是控制扫射的扳机。如果不松开扳机,机关枪就会持续射击。在开发中,类似地,只要鼠标不松开,相关事件就会持续触发。例如:

代码如下:

var resizeTimer=null;
$(window).on('resize',function(){
if(resizeTimer){
clearTimeout(resizeTimer)
       }
resizeTimer=setTimeout(function(){
console.log("window resize");
},400);

函数防抖(debounce)原理与应用

debounce

debounce(防抖)与 throttle 相似,但 debounce 要求空闲时间必须大于或等于指定值时,才会执行调用方法。debounce 控制的是空闲时间的间隔。例如在实现 autocomplete(自动补全)功能时,需要很好地控制输入文字时调用方法的时间间隔。通常第一个输入的字符会立即开始调用,随后根据一定的时间间隔重复执行该方法。对于极端输入情况,例如按住某个键不放时,这种方法特别有效。

debounce 主要应用场景包括: 文本输入时的 keydown 和 keyup 事件,例如实现 autocomplete 功能。

网上有许多相关方法,例如 Underscore.js 对 throttle 和 debounce 进行了封装。jQuery 也有一个 throttle 和 debounce 的插件:jQuery throttle / debounce,所有原理相同,实现的功能也一致。这里提供一个常用的 throttle 和 debounce 控制函数:

代码如下:

/*
* 频率控制 返回函数连续调用时,fn 执行频率限定为每多少时间执行一次
* @param fn {function} 需要调用的函数
* @param delay {number} 延迟时间,单位毫秒
* @param immediate {bool} 给 immediate 参数传递 false 绑定的函数先执行,而不是 delay 后后执行。
* @return {function}实际调用函数
*/
var throttle = function (fn,delay, immediate, debounce) {
var curr = +new Date(),//当前事件
last_call = 0,
last_exec = 0,
timer = null,
diff, //时间差
context,//上下文
args,
exec = function () {
last_exec = curr;
fn.apply(context, args);
       };
return function () {
curr= +new Date();
context = this,
args = arguments,
diff = curr - (debounce ? last_call : last_exec) - delay;
clearTimeout(timer);
if (debounce) {
if (immediate) {
timer = setTimeout(exec, delay);
} else if (diff >= 0) {
exec();
           }
} else {
if (diff >= 0) {
exec();
} else if (immediate) {
timer = setTimeout(exec, -diff);
           }
       }
last_call = curr;
   }
};
/*
* 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 delay,fn 才会执行
* @param fn {function} 要调用的函数
* @param delay {number} 空闲时间
* @param immediate {bool} 给 immediate 参数传递 false 绑定的函数先执行,而不是 delay 后后执行。
* @return {function}实际调用函数
*/
var debounce = function (fn, delay, immediate) {
return throttle(fn, delay, immediate, true);
作者最新文章