☰
JavaScript 防抖和节流
2026/10/13 9:13:35 网站建设 项目流程

文章目录

  • JavaScript 防抖和节流
    • 防抖(Debounce)
      • 概念
      • 代码实现
      • 完整代码
    • 节流(Throttle)
      • 概念
      • 代码实现
      • 完整代码
    • 对比
    • 按钮防止频繁点击

JavaScript 防抖和节流

防抖(Debounce)

概念

核心思想:

停止触发后延迟执行。如果在等待期间又触发事件,就重新计时。

类比:

等电梯:如果有人进来了,电梯就重新计时关门,知道没有人再进才关门运行。

场景:

  • 搜索框实时联想(输入完后才发送请求)
  • 表单输入校验(输入完后才校验)
  • 窗口 resize 结束后重新布局
  • 按钮重复点击防护

代码实现

初始代码:

functiondebounce(fn,delay){lettimer=nullreturnfunction(...args){if(timer)clearTimeout(timer)timer=setTimeout(()=>{fn.apply(this,args)},delay)}}

增加立即执行功能:

functiondebounce(fn,delay,immediate){lettimer=nullletisDebounced=false// 是否防抖模式returnfunction(...args){if(timer)clearTimeout(timer)if(immediate&&!isDebounced){fn.apply(this,args)// 立即执行后进入防抖模式isDebounced=true}else{timer=setTimeout(()=>{fn.apply(this,args)// 防抖模式结束,下次输入内容立即执行isDebounced=false},delay)}}}

增加取消功能:

functiondebounce(fn,delay,immediate){lettimer=nullletisDebounce=false// 是否进入防抖模式const_debounce=function(...args){if(timer)clearTimeout(timer)if(immediate&&!isDebounce){fn.apply(this,args)// 立即执行后进入防抖模式isDebounce=true}else{timer=setTimeout(()=>{fn.apply(this,args)// 防抖模式结束,下次输入内容立即执行isDebounce=false},delay)}}_debounce.cancel=function(){if(timer)clearTimeout(timer)timer=nullisDebounce=false}return_debounce}

完整代码

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>防抖</title></head><body><inputid="searchInput"type="text"placeholder="请输入"><divid="searchResult"></div><buttonid="btnCancel">取消</button><script>functiondebounce(fn,delay,immediate){lettimer=nullletisDebounce=false// 是否进入防抖模式const_debounce=function(...args){if(timer)clearTimeout(timer)if(immediate&&!isDebounce){fn.apply(this,args)// 立即执行后进入防抖模式isDebounce=true}else{timer=setTimeout(()=>{fn.apply(this,args)// 防抖模式结束,下次输入内容立即执行isDebounce=false},delay)}}_debounce.cancel=function(){if(timer)clearTimeout(timer)timer=nullisDebounce=false}return_debounce}constsearchInput=document.querySelector("#searchInput")constsearchResult=document.querySelector("#searchResult")constbtnCancel=document.querySelector("#btnCancel")constdebounceFn=debounce((e)=>{searchResult.innerHTML=e.target.value.trim()},1000,true)searchInput.addEventListener("input",debounceFn)btnCancel.addEventListener("click",()=>{debounceFn.cancel()})</script></body></html>

节流(Throttle)

概念

核心思想:

每隔固定时间执行一次。不管你触发多频繁,都按固定频率执行。

类比:

水龙头:拧开水龙头后水固定流速流出,不会英文你一直拧就无限加速。

场景:

  • 滚动事件
  • 鼠标移动
  • 输入框实时字数统计
  • 游戏中的按键连续响应

代码实现

初始代码:

functionthrottle(fn,interval){letlastTime=0returnfunction(...args){constnowTime=newDate().getTime()if(nowTime-lastTime>=interval){fn.apply(fn,args)lastTime=nowTime}}}

控制立即执行和最后一次执行功能:

节流函数默认会立即执行,可以通过 leading 变量控制是否立即执行。

functionthrottle(fn,interval=500,leading=false,trailing=true){letlastTime=0lettimer=nullreturnfunction(...args){letnowTime=Date.now()// 首次不立即执行// !lastTime表示第一次执行if(!lastTime&&!leading){lastTime=nowTime}// 计算等待时间,<=0时执行函数constwaitTime=interval-(nowTime-lastTime)// 执行节流函数if(waitTime<=0){if(timer){clearTimeout(timer)timer=null}fn.apply(this,args)lastTime=nowTimereturn}// 执行最后一次if(trailing&&!timer){timer=setTimeout(()=>{fn.apply(this,args)lastTime=nowTime timer=null},waitTime)}}}

增加取消功能:

functionthrottle(fn,interval=500,leading=false,trailing=true){letlastTime=0lettimer=nullconst_throttle=function(...args){letnowTime=Date.now()// 首次不立即执行// !lastTime表示第一次执行if(!lastTime&&!leading){lastTime=nowTime}// 计算等待时间,<=0时执行函数constwaitTime=interval-(nowTime-lastTime)// 执行节流函数if(waitTime<=0){if(timer){clearTimeout(timer)timer=null}fn.apply(this,args)lastTime=nowTimereturn}// 执行最后一次if(trailing&&!timer){timer=setTimeout(()=>{fn.apply(this,args)lastTime=nowTime timer=null},waitTime)}}_throttle.cancel=function(){if(timer)clearTimeout(timer)timer=nulllastTime=0}return_throttle}

完整代码

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>节流</title></head><body><textareaid="searchInput"cols="30"rows="10"placeholder="请输入"></textarea><divid="searchResult"></div><buttonid="btnCancel">取消</button><script>functionthrottle(fn,interval=500,leading=false,trailing=true){letlastTime=0lettimer=nullconst_throttle=function(...args){letnowTime=Date.now()// 首次不立即执行// !lastTime表示第一次执行if(!lastTime&&!leading){lastTime=nowTime}// 计算等待时间,<=0时执行函数constwaitTime=interval-(nowTime-lastTime)// 执行节流函数if(waitTime<=0){if(timer){clearTimeout(timer)timer=null}fn.apply(this,args)lastTime=nowTimereturn}// 执行最后一次if(trailing&&!timer){timer=setTimeout(()=>{fn.apply(this,args)lastTime=nowTime timer=null},waitTime)}}_throttle.cancel=function(){if(timer)clearTimeout(timer)timer=nulllastTime=0}return_throttle}constsearchInput=document.querySelector("#searchInput")constsearchResult=document.querySelector("#searchResult")constbtnCancel=document.querySelector("#btnCancel")constthrottleFn=throttle((e)=>{searchResult.innerHTML="共计:"+e.target.value.trim().length+"字"},2000)searchInput.addEventListener("input",throttleFn)btnCancel.addEventListener("click",()=>{throttleFn.cancel()})</script></body></html>

对比

按钮防止频繁点击

按钮防频繁点击,既不是常规防抖,也不是常规节流,而是「立即执行 + 冷却锁定」。如果非要在两者里选,优先选节流的 “立即执行版”(leading-edge),但实际项目里更常见的做法是直接用按钮disabled状态 + 一个锁标志。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询