详解JS函数防抖:原理、实现与双版本应用

作者:寒星时间:2026-10-23 19:18:11浏览:236

本文深入解析JavaScript中的函数防抖(debounce)技术,阐述其在高频事件如resize、scroll中的必要性。通过电梯等待的通俗案例说明防抖核心逻辑,并提供基础及结合立即执行与非立即执行的完整代码实现,最后总结搜索验证、窗口调整等典型应用场景,帮助开发者提升前端性能与代码质量。

函数防抖的基本概念与原理

一、什么是函数防抖

概念:函数防抖(debounce),是指事件触发后,在 n 秒内函数仅能执行一次;若在 n 秒内再次触发事件,则重新计算函数的延时执行时间。

以电梯场景为例,当检测到有人进入(触发事件)时,电梯会额外等待 10 秒;若在此 10 秒内再次有人进入(重复触发事件),电梯将再次延长等待 10 秒。由此可见,“函数防抖”的核心机制在于:在特定事件发生后,经过一段指定时间才执行对应的动作。

前端高频事件触发的性能问题

二、为什么需要函数防抖

在前端开发中,onresize,scroll,mousemove ,mousehover 等事件极易被频繁触发(短时间内多次触发)。若不加限制,可能导致一秒内执行几十次甚至几百次。若此类函数内部调用了其他函数,特别是涉及 DOM 操作的函数(浏览器操作 DOM 性能开销极大),不仅会浪费计算资源、降低程序运行速度,甚至可能导致浏览器卡死或崩溃,此类问题后果严重。

此外,短时间内重复发起的 ajax 请求不仅会导致数据关系混乱,还会引发网络拥塞并增加服务器压力,因此必须解决这一问题。

函数防抖的实现机制与代码

三、函数防抖如何解决上述问题

基于对问题的分析,可以得出如下解决方案。

函数防抖的关键在于需要一个 setTimeout 来辅助实现,用于延迟执行目标代码。若方法被多次触发,则需清除上次记录的延迟执行代码(使用clearTimeout ),并重新开始计时。若在计时期间事件未被重新触发,待延迟时间结束,则执行目标代码。

四、函数防抖的代码实现

基于上述分析,我们对“函数防抖”进行简单的代码实现,如下所示:

基础防抖函数代码实现


function debounce(fn,wait){
 var timer = null;
 return function(){
  if(timer !== null){
   clearTimeout(timer);
  }
  timer = setTimeout(fn,wait);
 }
}
 
function handle(){
 console.log(Math.random());
}
 
window.addEventListener("resize",debounce(handle,1000));

函数防抖的典型应用场景

五、函数节流的使用场景

函数防抖通常适用于只需在连续事件发生后仅触发一次回调的场景。具体包括:

搜索框搜索输入:仅需在用户最后一次输入完成后,再发送请求;

用户名、手机号、邮箱输入验证;

浏览器窗口大小改变后:仅在窗口调整完成后,再执行 resize 事件中的代码,以防止重复渲染。

目前所遇到的应用场景即为此类。理解了原理与实现思路后,开发者可将其应用于任何需要的场合,从而提升代码质量。

立即执行与非立即执行版本的结合

总结

函数防抖实际上分为“立即执行版”和“非立即执行版”。从字面意思即可看出二者的区别:所谓“立即执行版”,是指触发事件后函数不会立即执行,而是在 n 秒后执行;若在 n 秒内再次触发事件,则重新计算函数的执行时间。而“非立即执行版”是指触发事件后函数会立即执行,随后在 n 秒内若不触发事件,则继续执行函数的效果。

在开发过程中,需根据具体场景选择使用哪个版本的防抖函数。一般而言,上述防抖函数已能满足大部分场景需求。但我们可以将非立即执行版和立即执行版的防抖函数结合,实现最终的双剑合璧版本的防抖函数,以下为简单的实现代码:

双版本结合的高级防抖实现


/**
* @desc 函数防抖---“立即执行版本” 和 “非立即执行版本” 的组合版本
* @param func 需要执行的函数
* @param wait 延迟执行时间(毫秒)
* @param immediate---true 表立即执行,false 表非立即执行
**/
function debounce(func,wait,immediate) {
let timer;

return function () {
let context = this;
let args = arguments;

if (timer) clearTimeout(timer);
if (immediate) {
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timer = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}

function handle(){
console.log(Math.random());
}

// window.addEventListener("mousemove",debounce(handle,1000,true)); // 调用立即执行版本
window.addEventListener("mousemove",debounce(handle,1000,false)); // 调用非立即执行版本

以上就是详解JS函数防抖的详细内容,更多关于JS函数防抖的资料请关注本站其它相关文章!

作者最新文章
相关文章
更多