函数节流与函数防抖

什么是函数节流与函数防抖

  • 函数节流:指定时间间隔内只会执行一次任务
  • 函数防抖: 事件被触发n秒后,任务才会执行,如果n秒内再次被触发,则重新计时。

举个🌰,我的理解中,节流就相当于技能冷却时间,每隔一段时间才能释放一次技能,冷却过程中不管多想放技能都无济于事;而防抖相当于外卖员等一段时间没有新的外卖,就将手上的外卖一起派送一次,期间如果来了新的外卖,就抛弃这次送外卖的想法,重新等待。

那么为什么需要节流与防抖呢?

总得来说就是要限制函数调用的频次,优化性能

js中的一些事件如浏览器的resize、scroll,鼠标的mousemove、mouseover,input输入框的keypress等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能。为了优化体验,就需要对这类事件进行调用次数的限制。

简单实现

函数节流(throttle)

根据节流的理念,可以先梳理其实现逻辑:

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(fn, delay){
let canRun = true
return function(){
if(canRun){
fn.apply(this, arguments)
canRun= false
setTimeout(()=>canRun = true, delay)
}
}
}
const throttled = throttle(()=>console.log('hi'))
throttled()
throttled()

函数防抖(debounce)

防抖的逻辑梳理如下:

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function debounce(fn, delay){
let timerId = null
return function(){
const context = this // 取debounce执行作用域的this
if(timerId){window.clearTimeout(timerId)}
timerId = setTimeout(()=>{
fn.apply(context, arguments)
timerId = null
},delay)
}
}
const debounced = debounce(()=>console.log('hi'))
debounced()
debounced()

区别与应用场景

区别

  • 防抖侧重于一段时间内连续触发的事件,只在最后执行一次
  • 节流侧重于每隔固定的一段时间只执行一次

应用场景

节流 throttle

  • 高频点击提交,表单重复提交
  • 监听滚动事件,加载更多或滚到底部监听

防抖 debounce

  • 搜索联想,只需等用户最后一次输入完再发送请求
  • 手机、邮箱等验证时,进行输入检测
  • resize事件,等用户最后一次调整完浏览器大小再执行

总结

函数节流与函数防抖的原理其实非常简单,巧妙地使用 setTimeout 来存放待执行的函数,这样可以很方便的利用 clearTimeout 在合适的时机来清除待执行的函数。

使用函数节流与函数防抖的目的,就是为了限制函数调用的频次,节约计算机资源。

参考

https://juejin.cn/post/6844903669389885453#heading-7

https://juejin.cn/post/6844903926798516237