函数节流与函数防抖精析

作者: 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