防抖与节流的个人理解及其对应的应用场景

article/2025/11/3 14:46:31

什么是防抖和节流,他们的应用场景有哪些

防抖 (debounce)

防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。

想要了解一个概念,必先了解概念所应用的场景。在 JS 这个世界中,有哪些防抖的场景呢

  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存

代码如下,可以看出来「防抖重在清零 clearTimeout(timer)

function debounce (f, wait) {let timerreturn (...args) => {clearTimeout(timer)timer = setTimeout(() => {f(...args)}, wait)}
}

节流 (throttle)

节流,顾名思义,控制水的流量。控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似。

  • scroll 事件,每隔一秒计算一次位置信息等
  • 浏览器播放事件,每个一秒计算一次进度信息等
  • input 框实时搜索并发送请求展示下拉列表,没隔一秒发送一次请求 (也可做防抖)

代码如下,可以看出来「节流重在开关锁 timer=null

function throttle (f, wait) {let timerreturn (...args) => {if (timer) { return }timer = setTimeout(() => {f(...args)timer = null}, wait)}
}

总结 (简要答案)

防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout

节流:控制流量,单位时间内事件只能触发一次,如果服务器端的限流即 Rate Limit。代码实现重在开锁关锁 timer=timeout; timer=null
在这里插入图片描述

防抖与节流

面试准备 - JS 防抖与节流

函数防抖和节流,都是控制事件触发频率的方法。 

https://zhuanlan.zhihu.com/p/72923073

节流: 防止暴力点击(单位时间内第一次执行)放暴力点击:最好的办法,通过设置布尔类型的变量(比如按钮;disabled  或者loading)来控制,判断状态,如果为true,则 return 掉 

防抖: 搜索框的运用(单位时间内最后一次执行)

 

函数防抖(debounce):在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

看一个?(栗子):

<body>没有防抖的input:<input type="text" id="unDebounce"><br>防抖后的:      <input type="text"><br>节流后的:       <input type="text"><script>//没有防抖的function ajax(content){console.log('ajax request '+content)}let inputa=document.getElementById("unDebounce")inputa.addEventListener("keyup",function(e){ajax(e.target.value)})//-----------------------------------------</script>
</body>

可以看到,我们只要按下键盘,就会触发这次ajax请求。

不仅从资源上来说是很浪费的行为,而且实际应用中,用户也是输出完整的字符后,才会请求。下面我们优化一下:

 没有防抖的input:<input type="text" id="unDebounce"><br>防抖后的:      <input type="text" id="Debounce"><br>节流后的:       <input type="text"><script>//防抖的function ajax(content){console.log('ajax request '+content)}function  debounce(fun,time){return function(args){let that=this;clearTimeout(fun.id);fun.id=setTimeout(function(){fun.call(that,args)},time)}}let inputDebounce=document.getElementById("Debounce")let debounceAjax = debounce(ajax, 500)inputDebounce.addEventListener('keyup',function(e){debounceAjax(e.target.value)})</script>

 

 

关于页面窗口变化触发某个方法,首先想象一下,假如用鼠标拉缩页面,你感觉你就拉缩了一下,但是浏览器判断你是触发了很多次,如果处理的函数很复杂,这样在短时间内多次处理相同的事件,会非常的消耗内存,这时就需要用到防抖。这个例子没看懂,没关系,下面就自己理解,来聊聊到底什么是函数防抖(debounce)与函数节流(throttle)。

举个例子,用户输入身份证,然后接收用户输入的内容,发送给后台。如果在输入框上绑定一个input事件,用户输入内容时,触发事件然后获取内容,然后发送一个ajax请求。假如用户输入了一个数字,监听事件触发,发送一个请求,当用户在输入第二个数字的时候又触发事件,发送请求,无线下去直至用户停止输入。但是前面发送的信息并不是我们想要的,我们想要的是用户完整的身份证信息。但是监听事件在触发时,就会发生,也就是每输入一个数字就会触发,怎么办,这时聪明的程序猿就想到了,运用定时器来延迟函数执行。但单纯的延迟执行并不行,还是会重复执行,只不过延后了执行的时间,我们希望的是当用户停止输入后,获取内容。也就是当用户不在触发事件时定时器执行方法。

对于上面这个案例,解决办法就是在触发事件时,设置一个定时器setTimeout,但在一开始执行时会先清除本次操作中存在的定时器,然后在设置定时器,在几秒后执行该函数。当再次触发事件监听执行函数时,会清除之前的定时器,然后在执行定时器。当不在触发事件时,保留的定时器才开始生效然后执行函数。

下面来模拟一个功能,提供一个输入框,然后用户输入内容,然后处理用户输入的内容。具体怎么深度处理,我暂时没想到,这里我用打印来模拟处理的函数。下面直接看代码。

 function debounce(fn,delay){  //创建一个闭包函数,确保内部的变量不会被销毁,即保留上一次的timervar   timer;return function(){     //这里需要返回出去一个函数,让外部接受,这也是形成闭包的主要原因var self=this,args=arguments;  //在外部先保存一份当前this的指向,定时器里this指向的是全局,为了防止偏移,所以我们需要重新绑定thisclearTimeout(timer);     //这里先清除上次创建的定时器,防止定时器执行 timer=setTimeout(function(){    //这里设置定时器,重新启动定时fn.apply(self,args)    //定时器内修改要执行的方法的this指向,并执行函数。},delay);}};var vel=debounce(function(e){       //外部接受闭包里面返回的函数console.log(e.target.value)},1000);document.querySelector("input").addEventListener("input",vel);

梳理一下为什么要这么写;注释解释了每一行的内容和为什么要这么写,但是有些概念可能还是没清楚。闭包这里不用说了,注释解释的很清楚。为什么需要保存一份this,因为后续我们需要用到定时器,因为定时器的机制就在那,定时器内this指向的是window。所以一般遇到定时器,我们都会在外部保存一份this。

为什么要先清除定时器呢,函数防抖本来就是要解决,假如高频率触发事件,会非常消耗性能,所以在触发事件时,利用定时器的功能,几秒后在执行我们需要执行的函数,这里虽然起到了延时执行,但是多次触发就会多次生成多个定时器,这样做反而没有意义。所以需要在一开始就先清除上一次保存的定时器,这样在不超过定时器规定的时间内如果再次触发了事件,那么就会消除上一次的定时器,然后在生成一个定时器,生成消除生成消除,到最后停止了,这中间其实就只生成了一个定时器。

最后就是为什么定时器内的函数要修改this指向。上面说过,定时器里的this指向的全局,假如我们不修改绑定,我们是找不到e.target.value的值的。为什么?因为在定时器里执行console这段函数时,this执行的是全局,但是我们的事件是触发在输入框这个节点上,而内容也是获取输入框内输入的内容,所以在全局上是找不到内容的。

  • 用户在搜索的时候,在不停敲字,如果每敲一个字我们就要调一次接口,接口调用太频繁,给卡住了。
  • 输入(电话号码等输如)用防抖来节约请求资源。
  • 搜索(每输入一次就执行过滤一次)
  • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

函数节流,其实函数节流和函数防抖相似,但是也有区别。函数防抖是在事件一直触发时我们去消除定时执行的任务,这样就会造成如果事件不停止,我们的任务就不会执行。而函数节流则是选择一个折中的方法,比如如果操作次数的间隔时间大于我们规定的这个时间,就执行一下方法,同时当事件结束时我们也需要再次执行一下方法,为什么?比如在短时间内高频率的输入内容,这个时间是小于规定的时间,这时就不会触发方法,所以我们需要在事件结束后,利用定时器在去执行这个方法。

还是没懂啥是节流?没关系下面,我们在来模拟一个场景。不知道大家有没有遇到过地铁高峰期。或者是春运高峰期。反正北京的春运高峰期特别在返程时,客流量特别大,就如上图那样。空间就这么大,站台的承受能力有限,如果我们不限制人流量进入站台,那么空间只会原来越拥挤,而且也存在很多隐患。怎么办,节流出现了。下面这个情景你肯定也遇到过。

首先我们不限制流量进入,但是会控制流量的进入时间。常见的就是在火车站过安检。都会设有相关人员在进站口控制进站,当一段时间内进站的人数过多时,相关人员就会拉封条,禁止旅行者进入。然后一段时间以后在打开封条,让旅行者继续进站。这就是我们说的节流。

代码如下。建议自己也敲一遍看看效果,这样更容易掌握。

function throttle(fn,threshhold) {var timer;var start=new Date;var threshhold=threshhold||160;return function () {var self=this,args=arguments,cur=new Date() - 0;clearTimeout(timer);if (cur-start>=threshhold){console.log("now",cur,cur-start);fn.apply(self,args);start=cur;}else {timer=setTimeout(function () {fn.apply(self,args);},threshhold);}}}var mousemove=throttle(function (e) {console.log(e.pageX,e.pageY)});document.querySelector("#panel").addEventListener("mousemove",mousemove)

说一下代码都做了什么。首先写一个正方形,然后在正方形上绑定一个mousemove事件,然后打印出,当前鼠标的位置。你要知道你的鼠标灵敏度其实是很高的,你只要丝毫动一下就会触发这个事件的,然后就会立马打印出位置。假如我们只需要鼠标移动结束后落定的位置,用函数防抖就可以实现。如果鼠标持续晃动,我们想获取一段时间内的定位,例如每隔1秒获取鼠标落定的位置。这样就既保证了在滑动过程中也能触发我们想要执行的方法,高频率触发事件时不会出现大量的运行。

最后你还是没有看懂我说的函数节流与函数防抖,好吧,在给你安利个关于函数节流的小乐子。一位用户在登录界面输入了账号、密码。然后快速点击了10次登录按钮,结果连续弹出三次密码错误,随后提示输入密码错误超过三次,您的账号已被锁定。但是,假如用到了事件节流就不会出现这种情况了。我们只要设置在开始点击几秒以后执行一次方法,这样就不会出现连续触发连续执行方法了。

总结

函数节流、函数防抖
两者都是用来解决代码短时间内大量重复调用的方案。
当然,也是各有利弊。
在实际开发中,两者的界定也很模糊。
比如搜索关键字联想,用节流或者防抖都可以来做,拖拽DOM、监听resize等等,这两个都是可以来实现的。

两者的区别在于:
函数节流在一定时间内肯定会触发多次,但是最后不一定会触发
函数防抖可能仅在最后触发一次

 

 

 

 

 


http://chatgpt.dhexx.cn/article/9gC8CJ5M.shtml

相关文章

JS防抖和节流

欢迎学习交流&#xff01;&#xff01;&#xff01; 持续更新中… 文章目录 防抖节流二者区别应用场景 防抖和节流都是为了项目优化而出现的&#xff0c;官方没有具体定义的&#xff0c;他们的出现主要是为了解决一些短时间内连续执行的事件带来性能上的不佳和内存的消耗巨大等…

手写防抖节流

文章目录 手写前端常用技巧-防抖节流防抖节流1. 首节流2. 尾节流3. 首尾节流 总结 手写前端常用技巧-防抖节流 防抖&#xff1a;当持续触发事件时&#xff0c;一定时间内没有再触发事件&#xff0c;才会在一段时间之后触发事件处理函数。 节流&#xff1a;当持续触发事件时&am…

防抖和节流

1. 什么是防抖 防抖策略&#xff08;debounce&#xff09;是当事件被触发后&#xff0c;延迟 n 秒后再执行回调&#xff0c;如果在这 n 秒内事件又被触发&#xff0c;则重新计时。 1.2. 防抖的应用场景 用户在输入框中连续输入一串字符时&#xff0c;可以通过防抖策略&…

lodash节流

滚动条事件优化 可以用 lodash节流 npm i -S lodash Lodash 简介 | Lodash 中文文档 | Lodash 中文网

JS 节流

JS 节流 说明: 1.对于高频触发的监听事件函数,实现对于触发次数的间接限制,从而降低触发次数. 2.关键点在于控制时间周期内,阻止触发内容,即上锁;在时间周期外解锁,触发内容。 3.主要是对间隔时间限制,在规定时间内,阻止触发事件内指定程序或默认抛弃 4.三种实现节流方式:时间…

个人对于节流的理解!

文章目录 前言一、节流是什么&#xff1f;二、节流的实现总结 前言 防抖和节流是前端经常会被提起以及涉及到的内容&#xff0c;更是前端性能优化的手段之一&#xff0c;我初学防抖和节流也遭遇了很多坑&#xff0c;所以想写一篇博客一则当作学习笔记&#xff0c;二则如果能帮…

节流的基本使用以及理解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、节流是什么&#xff1f;应用场景 二、使用步骤1.定义节流阀2.绑定 mousemove 事件3. 判断节流阀是否为空&#xff0c;如果不为空,说明距离上一次执行时间还没有…

图片跟随鼠标样式跟随效果(附完整代码及效果)

Demo效果如下&#xff1a; 完整代码如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta …

前端必备技能之----节流

&#xff08;引言----和大佬们出去吃饭总是会有收获的&#xff0c;这个知识点是我之前从未考虑过的事情&#xff0c;但是在现代的设计开发之中却是非常重要且使用频率非常之高的两个概念。&#xff09; 作为一个前端的初学者&#xff0c;因为之前淋过雨&#xff0c;所以想为同…

html锚点链接小案例

案例1&#xff1a;回到首页 <html ><head><meta charset"utf-8"><title></title><style type"text/css"> *{border: 0;margin: 0; padding: 0;}.box1, .box2{height: 3000px; width: 200px;background-color: green…

HTML锚点为什么叫hash,锚点链接和hash属性

相信大家挺经常见过这样一个效果。有一个很长很长的页面,分成好几部分,目录中一点击,就能定位到页面某个位置。 例如:有这样一个目录,例如你点击一下“HTML”,就会直接跳转到“HTML”的页面位置 这就是锚点链接(也叫书签链接),常常用于那些内容庞大繁琐的网页,通过点击…

html5添加锚点锭接,为页面添加锚点链接

为页面添加锚点链接 开哈础是发通待质击文以为近哈知按分过续的战发中会遇到为页面中添加锚点链接的需求,即在页面中点击某处,可以跳转到与之有联系的地方。添加锚点的方法比较多,在这儿,把常用的方法大享上。是发了概开程态间些告人屏果会区。一一是控标近体到班都一从小述…

菜鸟 html锚链接,Vue锚点链接

锚点链接是我们在开发中经常会用到的一个技术点&#xff0c;常见的常见有&#xff0c;页面内容过多&#xff0c;而我们不希望拿鼠标一直来回滚动&#xff0c;就需要用到锚点链接&#xff0c;以 " 目录 " 的方式来进行对应的跳转。 而在常见的项目中&#xff0c;锚点链…

制作图片锚点链接html,锚点链接怎么做

网页内容过多时我们可以使用锚点链接来进行位置的跳转&#xff0c;通过锚点链接我们不但可以指向文档&#xff0c;还能指向页面里的特定段落&#xff0c;这样就会便于我们来浏览网页中的内容&#xff0c;那么&#xff0c;锚点链接怎么实现呢&#xff1f;本篇文章就来给大家介绍…

web前端学习26(锚点链接)

文章目录 4.7.2 链接分类 4.7.2 链接分类 锚点链接&#xff1a;点我们点击链接&#xff0c;可以快速定位到页面中的某个位置。 在链接文本的href属性中&#xff0c;设置属性值为#名字的形式&#xff0c;如< a href"#two">第2集< /a> 点完这个链接就会跳…

Web容器版本泄露漏洞修复

0x00 背景 恶意攻击者可以根据版本信息寻找相关漏洞&#xff0c;进行利用漏洞攻击 0x01 修复思路 通过修改配置或者配置错误提示页面&#xff0c;隐藏 web容器的版本号及其它敏感信息。 0x02 代码修复 Apache 版本号 隐藏 Apache 的版本号及其它敏感信息&#xff0c;配置操…

Spring容器 SpringMVC容器 web容器的关系

说到spring和springmvc&#xff0c;其实有很多工作好多年的人也分不清他们有什么区别&#xff0c;如果你问他项目里用的什么MVC技术&#xff0c;他会说我们用的spring和mybatis&#xff0c;或者spring和hibernate。 在潜意识里会认为springmvc就是spring&#xff0c;之前我也是…

SpringBoot深入(一)--SpringBoot内置web容器及配置

版权声明&#xff1a;作者原创&#xff0c;转载请注明出处。 本系列文章目录地址&#xff1a;http://blog.csdn.net/u011961421/article/details/79416510 前言 在学会基本运用SpringBoot同时&#xff0c;想必搭过SSH、SSM等开发框架的小伙伴都有疑惑&#xff0c;SpringBoot在…

SpringBoot内置web容器及配置

前言 在学会基本运用SpringBoot同时&#xff0c;想必搭过SSH、SSM等开发框架的小伙伴都有疑惑&#xff0c;SpringBoot在spring的基础上做了些什么&#xff0c;使得使用SpringBoot搭建开发框架能如此简单&#xff0c;便捷&#xff0c;快速。本系列文章记录博主网罗博客、分析源码…

Web 容器、HTTP 服务器 、Servlet 容器区别与联系

首先浏览器发起 HTTP 请求&#xff0c;像早期的时候只会请求一些静态资源&#xff0c;这时候需要一个服务器来处理 HTTP 请求&#xff0c;并且将相应的静态资源返回。 这个服务器叫 HTTP 服务器。 简单点说就是解析请求&#xff0c;然后得知需要服务器上面哪个文件夹下哪个名字…