世界睡了🌙,故事醒着。
对JavaScript中节流和防抖函数的一些思考和总结
发布时间:2024/09/16
浏览量:...

首先,什么是节流和防抖。

节流:在单位时间内,只触发一次事件。

防抖:在单位时间内,只执行最后一次触发的事件。

这里的事件可以简单的理解为函数。

节流函数能够控制单位时间内函数执行的频率,那么它的使用场景就很明显了,在用户交互或者网络请求这样需要频繁触发操作的中,我们可能会用到节流函数对触发操作进行限制,以此减少函数执行的频率,来进行一些优化。比如:自动补全、拖拽操作、滚动事件、窗口尺寸的监听、复杂动画效果、鼠标移动事件、网络请求等

防抖函数能够避免在单位时间内多次触发同一时间,从而能够很好地避免短时间内由于同一操作引发的一些性能问题。与节流函数不同的是,防抖是保证只执行最后一次调用的函数。在用户搜索时可以保证只有在用户停止输入一段时间后才会发起搜素请求,以减少不必要的请求;监听页面scroll事件时,如果每次滚动都触发相应逻辑,可以会导致页面卡顿,使用防抖可以保证在用户停止滚动一段时间后在执行逻辑。

节流-防抖

接下来,使用JavaScript手写实现节流函数和防抖函数

/**
 * 节流函数
 * @param {Function} func 要执行的函数
 * @param {number} wait 单位时间(ms)
 */
const throttle = (func, wait) => {
  let timer = null
  return () => {
    if (!timer) {
      timer = setTimeout(() => {
        func()
        timer = null
      }, wait)
    }
  }
}

/**
 * 防抖函数
 * @param {Function} func 要执行的函数
 * @param {number} wait 单位时间(ms)
 */
const debounce = (func, wait) => {
  let timer = null
  return () => {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      func()
    }, wait)
  }
}

我们使用setTimeout实现了一个最简单的节流函数和防抖函数,但是在实际的开发过程中,如果我们想要实现一个更加通用的节流/防抖函数,我们往往需要考虑更多的东西:

  • 函数的灵活性和可配置性
  • 如何进一步优化性能,比如考虑使用requestAnimationFrame来实现函数(如果浏览器环境支持),而不是setTimeout
  • 类型检查和错误处理,便于开发调试
  • 是否存在需要取消当前正在等待的函数的执行的情况
  • 是否存在需要强制立即执行函数无需等待设定的时间的情况

在开发中,只考虑特定的情况去处理往往并不是很难,而当我们需要去实现一个通用的解决问题的方案时,事情往往就会变得麻烦起来,这时候对我们自身的编程能力就是极大的考验,思考问题需要有足够的宽度和广度,道阻且长啊。