> 文章列表 > 防抖与节流总结

防抖与节流总结

防抖与节流总结

最近复习到了防抖与节流,今天就把防抖与节流给总结一下吧。

防抖

什么是防抖

防抖是一种常用的前端优化技术,它可以有效地减少在用户频繁触发某些事件(比如鼠标滚动、窗口缩放等)时产生的多次执行函数的问题。这样可以避免函数被频繁调用,从而提高页面的性能和用户体验。

什么时候使用防抖

  1. 输入框搜索:在用户输入关键字搜索时,若是有着自动补全事件,防抖就可以避免频繁请求,提高搜索效率。
  2. 按钮点击:在按钮被连续点击时,防抖函数可以避免重复触发事件,从而避免页面卡死以及产生不可预期的后果,提高用户体验。
  3. 页面滚动:在页面滚动时,避免频繁地触发滚动事件,提高性能和体验。
  4. 窗口缩放:在窗口大小发生改变时,避免频繁地触发事件,等待窗口调整完成后,再执行resize事件中的代码,提高性能和体验。
  5. 表单验证:在表单验证时,避免频繁地触发验证事件,提高效率和体验。

防抖的实现原理

定时器实现防抖是在事件触发后设定一个延时时间,在这个时间内如果再次触发了同样的事件,就会重新开始计时,直到延时时间结束后才会执行函数。

防抖函数的代码

function debounce(fn,delay){let timer = null;return function(){let context = this;let args = arguments;if(timer){clearTimeout(timer);timer = null;}timer = setTimeout(()=>{fn.apply(context,args);},delay);}
}

这里传入的参数fn是我们需要处理的函数,delay是我们设定的延时时间。

防抖的缺陷

  1. 无法立即执行函数,需要等待一定的时间后才能执行。

  2. 如果在等待时间内再次触发函数,就会重新计时,可能会导致函数执行的次数少于期望值。

  3. 如果设置的时间过长,会导致用户等待过久,降低用户体验。

节流

什么是节流

节流是一种优化性能的技术,主要用于减少某些事件的触发频率。在一些需要频繁触发事件的场景中,如果不加以限制,可能会造成系统负载过高,甚至导致卡顿或崩溃。节流技术就是通过限制事件触发的频率,来减少系统负载,提高性能。常见的节流方式包括定时器节流和时间戳节流。

什么时候使用节流

  1. 频繁的鼠标移动、滚动事件:比如浏览器滚动条的滚动、鼠标移动、拖拽等操作,会频繁触发事件,使用节流可以减少事件的触发次数。

  2. 窗口大小改变事件:当用户调整浏览器窗口大小时,会触发窗口大小改变事件,这个事件会在用户停止调整窗口大小后才会触发,因此使用节流可以减少事件的触发次数,提高性能。

  3. 输入框输入事件:比如用户在输入框中输入文字时,会触发输入事件,如果用户连续输入多个字符,会频繁触发事件,使用节流可以减少事件的触发次数,提高性能。

  4. 搜索框搜索事件:用户在搜索框中输入关键字进行搜索时,搜索框会频繁触发搜索事件,使用节流可以减少事件的触发次数,提高性能。

  5. 延迟加载:在滚动到页面底部时,可以使用节流控制请求的频率,减少服务器的压力和网络带宽的消耗。

  6. 防止重复提交:比如用户连续多次点击提交按钮,会触发多次提交事件,使用节流可以减少事件的触发次数,避免重复提交。

节流的实现原理

时间戳实现节流

时间戳实现节流的原理是在触发事件时,记录一个时间戳,然后每次触发事件时都与上一次记录的时间戳进行比较,如果时间间隔大于等于指定的时间间隔,则执行函数并更新时间戳。如果时间间隔小于指定的时间间隔,则不执行函数。

定时器实现节流

定时器实现节流的原理是在执行时创建一个定时器,定时器到期则执行函数,并将变量置为null。在此期间如果再次触发节流函数,则判断定时器是否为空,为空则重新创建一个定时器,否则直接返回。

节流函数的代码

时间戳实现节流

// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval) {// last为上一次触发回调的时间let last = 0// 将throttle处理结果当作函数返回return function () {// 保留调用时的this上下文let context = this// 保留调用时传入的参数let args = arguments// 记录本次触发回调的时间let now = +new Date()// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值if (now - last >= interval) {// 如果时间间隔大于我们设定的时间间隔阈值,则执行回调last = now;fn.apply(context, args);}}
}

定时器实现节流

function throttle(fn,interval){let timer = null;return () => {if(timer)return;timer = setTimeout(()=>{fn();timer = null;},interval);}
}

节流函数的缺陷

节流函数无法完全避免事件的重复执行,它只是降低了重复执行的频率。因此,在某些场景下,可能需要使用防抖函数来完全避免事件的重复执行。

节流与防抖的融合

不难发现,节流函数和防抖函数都有着各自的缺陷,因此我们可以将节流与防抖融合起来,在防抖中加入节流的思想,避免遇到急躁的用户持续触发事件,导致用户等待过久,降低用户体验的问题。

function throttle(fn, delay) {// last为上一次触发回调的时间, timer是定时器let last = 0, timer = null// 将throttle处理结果当作函数返回return function () { // 保留调用时的this上下文let context = this// 保留调用时传入的参数let args = arguments// 记录本次触发回调的时间let now = +new Date()// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值if (now - last < delay) {// 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器clearTimeout(timer)timer = setTimeout(function () {last = nowfn.apply(context, args)}, delay)} else {// 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应last = nowfn.apply(context, args)}}
}