函数节流与函数防抖精析

作者: hencins | 来源:发表于2019-07-02 14:50 被阅读4次

引用前人博客内容 《JavaScript高级程序》中关于函数节流概念的错误,本人也非常赞同作者关于写博客的态度。
另一篇释义清晰的文章 一定能看懂的函数防抖与函数节流

两者概念辨别

函数节流和函数防抖在一些应用场景上有重合,导致新手比较难以分辨到底谁是谁,引用文中释义准确的定义:

  • 函数节流 throttle 一个水龙头在滴水,可能一次性会滴很多滴,但是我们只希望它每隔 500ms 滴一滴水,保持这个频率。即我们希望函数在以一个可以接受的频率重复调用。
  • 函数防抖 debounce 将一个弹簧按下,继续加压,继续按下,只会在最后放手的一瞬反弹。即我们希望函数只会调用一次,即使在这之前反复调用它,最终也只会调用一次而已。

比如以监听一个resize事件为例,连续地多次调节窗口的大小:

  • 函数节流 throttle: 在你resize的过程中,每200ms就进行一次DOM调整响应。
  • 函数防抖 debounce: 只有当你这一次resize整个过程完成之后,才进行一次DOM调整。

所以它们的这个属性天然决定了各自适合的应用场景:

  • throttle-过程中:拖拽元素、搜索词联想(google/baidu每敲一个字母就会有响应)、canvas画板交互、屏幕向下滚动
  • debounce-完成后: 文本输入校验(手机号、邮箱)、搜索词联想(部分低频响应场合的替代方案)、屏幕向下滚动

它们两者在某些场合都可以使用,但效果会有所差别。比如屏幕滚动onscroll这一块,有的站点用节流来做,可以让你一直不断的下拉屏幕,这对于快速浏览场景,找图片找新闻标题会很好;但是如果是在看某块完整内容,如一篇新闻一个章节小说,体验效果就会很差,这时就适合用防抖来做。

两者的目的都是为了节省非必要的消耗,提升响应性能和保证其他逻辑层的稳定执行(不会被大量DOM渲染或重复执行的回调事件而导致响应滞后)。

函数节流 throttle

示例代码:

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <title>Throttle Test</title>
</head>
<body style="height:200vh;">
  <script>
    const throttle = (func = ()=>{}, interval = 250) => {
      let isFree = true;
      return function () {
        if (!isFree) return;
        isFree = false;
        setTimeout(() => { isFree = true }, interval); // 体会throttle是以一定频率来响应
        if (func) func();
      }
    }
    var scrollthrottle = throttle(() => console.log("Throttle Function"));
    document.body.onscroll = scrollthrottle;
  </script>
</body>
</html>

函数防抖 debounce

示例代码:

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body style="height:200vh;">
  <script>
    const debounce = (func = ()=>{}, wait = 250) => {
      let timer;
      return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
          if (func) func();
        }, wait); // 体会debounce是滞后于事件响应之后的效果
      }
    }
    var scrolldebounce = debounce(() => console.log('Debounce Function'));
    document.body.onscroll = scrolldebounce;
  </script>
</body>
</html>

增添一点区别:从代码中也可以看到,在节流中回调函数可以放在setTimeout里,也可放在外。而在防抖中只能放在setTimeout里了。注意到这点区别也是在不同场合使用不同方法的原因之一。

一句话总结

节流 过程中以一定频率执行回调,以一定频率连续响应
防抖 过程完成之后执行一次回调,在一段时间内只响应一次

相关文章

网友评论

    本文标题:函数节流与函数防抖精析

    本文链接:https://www.haomeiwen.com/subject/njwzcctx.html