本文详细解析JavaScript中函数节流与函数防抖的区别。通过代码示例说明,节流限制单位时间内的执行次数,适用于滚动监听;防抖则延迟执行并在空闲时触发,常用于输入验证。两者均通过控制执行频率优化浏览器性能,避免卡顿。
概念解释
一、概念解释
函数节流与函数防抖是优化高频执行JavaScript代码的两种常用手段。
理解这一机制可参考旧式电视机的工作原理:电子枪逐行扫描色彩并在屏幕上组成图像。由于人眼对频率的感知有限,当扫描频率足够高时,人眼无法察觉单独的扫描动作,而是将其融合为一张完整的画面。这类似于高速旋转的风扇,观察者看不到扇叶,只能看到一个圆形的视觉残留。
将此逻辑类比到JavaScript代码中,意味着在一定时间窗口内,代码无需执行极高频率的操作。只要达到特定的触发频率即可产生预期效果。过度执行不仅无法提升效果,反而消耗资源。因此,将JavaScript代码的执行次数控制在合理范围内,既能节省浏览器CPU资源,又能确保页面浏览流畅,避免因脚本执行导致的卡顿。这正是函数节流和函数防抖旨在解决的核心问题。
函数节流(Throttle)的核心定义是:在指定的时间间隔内,函数只执行一次。这类似于人类眨眼的动作,即在一段时间内只能眨眼一次。这是理解函数节流最直观的比喻。
函数防抖(Debounce)的核心定义是:在频繁触发事件的场景下,只有当足够长的空闲时间过去后,才执行一次代码。这类似于乘坐公交车的场景:如果乘客陆续刷卡上车,司机不会立即发车;只有当一段时间内没有新乘客刷卡时,司机才会启动车辆。
函数节流
二、函数节流
函数节流在实际开发中,最常见于监听页面元素的滚动事件。因为滚动事件属于高频触发事件,若不加控制,会严重影响性能。以下是监听页面元素滚动的示例代码:
// 函数节流
var canRun = true;
document.getElementById("throttle").onscroll = function(){
if(!canRun){
// 判断是否已空闲,如果在执行中,则直接return
return;
}
canRun = false;
setTimeout(function(){
console.log("函数节流");
canRun = true;
}, 300);
};
函数节流的关键在于声明一个标志位变量,用于记录当前代码是否正在执行中。
若该标志位表明当前处于空闲状态,则可以正常触发并执行方法。
若检测到代码正在执行中,则取消本次方法的执行请求,直接返回。
以下示例代码的作用是监听ID为throttle的元素上的滚动事件。
当变量canRun为true时,代表当前的滚动处理逻辑处于空闲状态,可以被调用。
通过判断条件if(!canRun),相当于获取了执行通行证。随后立即将canRun设置为false,即关闭关卡。这样,其他试图执行滚动事件的方法请求就会被拦截并拒绝。
接着,使用setTimeout设定最小时间间隔为300毫秒,并在该定时器回调中执行具体逻辑。
最后,只有当setTimeout内部的逻辑全部执行完毕后,才将canRun重置为true,释放关卡,允许下一次访问。
这种函数节流实现形式的注意事项在于,实际执行的间隔时间必须大于或等于300毫秒。如果具体执行的方法包含回调函数(callback),可以将将canRun=true的操作移至回调函数内部执行。理解了函数节流中“关卡”设置的核心逻辑后,对其进行调整便变得简单许多。
函数防抖
三、函数防抖
函数防抖的典型应用场景包括用户注册时的手机号码验证和邮箱格式验证。通常,只有当用户输入完毕并停止操作后,前端才发起格式检查请求;若格式不正确,再弹出相应的提示信息。以下仍以页面元素滚动监听为例进行解析:
// 函数防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
clearTimeout(timer); // 清除未执行的代码,重置回初始化状态
timer = setTimeout(function(){
console.log("函数防抖");
}, 300);
};
函数防抖的实现要点同样依赖于setTimeout来辅助完成代码的延迟执行。
若方法被多次触发,则需清除上一次记录的延迟执行代码,并重新开始计时。
若倒计时结束且期间没有新的方法触发请求,则执行预定的代码逻辑。
以下示例代码的作用是监听ID为debounce的元素上的滚动事件。
进入滚动事件处理函数后,首要操作是清除上一次未执行的setTimeout。该setTimeout的引用ID由变量timer记录。
clearTimeout方法允许传入无效值而不报错,因此此处可直接执行clearTimeout操作。
随后,将需要执行的代码封装在setTimeout中,并将该定时器引用重新赋值给timer进行缓存。
若在300毫秒的倒计时结束后,仍未有新的滚动事件触发,则执行setTimeout中封装的代码。
函数防抖的实现重点在于巧妙利用setTimeout作为缓存池,并能够轻松清除待执行的代码。
实际上,使用队列机制也能达到类似效果,此处不再深入展开。
在线demo
四、在线demo

这是一个测试Demo,将鼠标移至模块上方并滚动滚轮,即可在控制台查看输出效果。
Demo地址:https://wall-wxk.github.io/blogDemo/2017/02/15/throttleAndDebounce.html
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持本站!