节流和防抖

21 年 1 月 5 日 星期二
726 字
4 分钟

这是前端性能优化的基础知识,使用频率也非常高,建议掌握。

防抖

防抖,debounce /di'bauns/,它其实是来源于电学术语“去弹跳”。当你按下一个按钮时,由于信号传递十分迅速,但是部件在连接和断开状态之间不稳定,所以会多次触发信号。为了缓解这种情况,我们会在接收到按钮信号之后的一段时间内忽略来自它的信号。

在 JavaScript 中也是同理,如果遇到需要忽略一段时间内的同一个动作,只执行最后一次,那么就可以运用它来避免性能浪费。例如,在用户完成输入之后才显示搜索建议。

为了达到这一目的,可以使用定时器来延迟执行函数,下次触发时如果上一个定时器还没有结束,就取消它并创建一个新的定时器。完整代码是这样:

js
function debounce(fn, delay) {
  let timer
  return function () {
    let that = this,
      args = arguments
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(function () {
      fn.apply(that, args)
    }, delay)
  }
}

这是防抖函数的一种实现方式,其中涉及闭包和修改 this 指向的知识。

节流

再看节流,throttle /ˈθrɑːtl/。顾名思义就像在河道上建了一个水坝,目的是控制水的流速,不能彻底截断水流。

体现在 JavaScript 里就是函数执行一次后被锁定不允许触发,等一段时间再恢复触发。这有点像游戏里的技能 CD,你释放完技能后它就灰掉了,必须等待一段时间才可以继续释放。

截流函数的实现代码如下:

js
function throttle(fn, delay) {
  let wait = false
  return function () {
    let that = this,
      args = arguments
    if (!wait) {
      wait = true
      setTimeout(function () {
        fn.apply(that, args)
        wait = false
      }, delay)
    }
  }
}

它同样是使用定时器,与防抖不同的是,设置了一个标志在一段时间内锁定它。

对比

节流和防抖有点像,它们的不同之处在于,节流改变了频繁触发的函数的执行频率。

节流和防抖效果对比
节流和防抖效果对比

你可以通过 这个页面 去实际体验它们的不同。

总结

一般遇到 高频率事件 就需要注意了,是否会对浏览器性能照成影响,是否需要使用节流和防抖动?
根据它们各自的功能,针对业务场景可以自由的选择使用。使用节流的地方也可以使用防抖,具体看你希望达到的效果。

它们的核心内容不复杂,但是在日常开发中,我不会自己去单独实现它们,而是会使用开源库1提供的方法,这样更加安全和方便。

参考

  1. Lodash 中已经封装了这两个函数。

文章标题:节流和防抖

文章作者:柃夏chapu

文章链接:https://www.lxchapu.com/posts/throttle-and-debounce[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。