JS性能优化-防抖与节流

136 阅读2分钟

前言

在JavaScript中,当一个事件发生时,例如用户输入、滚动事件等,我们可能会触发一个函数来处理这个事件。如果没有对函数的执行进行限制,这个函数可能会被频繁地调用,导致性能问题和不必要的操作。而防抖节流这两种常用的优化方法,就是用于限制函数的执行频率,以提高性能和流畅度,减少不必要的资源消耗。

防抖(debounce)

防抖会等待最后一次操作完成后的一段时间,如果还有其他的操作请求,在此期间被触发,则重新计时。这样可以保证在一段时间内只执行一次函数,而不是频繁地执行。这对于输入框的自动完成搜索建议非常有用,当用户停止输入一段时间后,才发送请求。

//代码如下
    <button id="btn">提交</button>

    <script>
      function foo(e, a, b) {
        console.log(this, "按钮点击", e);
      }
      //获取botton节点并监听他的点击事件,当点击时触发防抖函数
      let btn = document.getElementById("btn");
      btn.addEventListener("click", debounce(foo, 1000));

      function debounce(fn, delay) {
        let timer;
        return function () {
          let args = arguments;//debounce执行时传入的所有参数
          
          //第一次点击时timer为undefined,跳过条件判断,并为其赋值一个定时器
          //随后每次点击都会重置定时器,直到用户点击后1s内没有再次点击才会执行完这个定时器
          if (timer) clearTimeout(timer);
          timer = setTimeout(() => {
            //当前fn的实际函数foo在全局中,使用call方法在delay时间后将当前this上下文和传入的参数指向foo函数
            fn.call(this, ...args);
          }, delay);
        };
      }
    </script>
  </body>

节流(throttle)

节流会限制在一定时间内只能执行一次函数,即使在这个时间内多次触发了事件。节流可以保证在一段时间内有规律地执行函数,而不是频繁地执行。这对于滚动事件处理非常有用,使用节流后滚动不再会不断地调用函数,而是会在滚动停止后固定时间间隔执行一次函数。

//代码如下
<body>
    <button id="btn">提交</button>
    <script>
        function foo(e){
            console.log(this,"提交了",e);
        }
        
        let btn = document.getElementById('btn')
        btn.addEventListener('click',throttle(send,1000))

        function throttle(fn,delay){
            let args = arguments
            let last = Date.now()//获取最后一次点击时间
            return function(){
                当当前时间和你最后一次点击的时间差大于delay时,才会执行foo函数
                if(Date.now()-last>delay){
                    fn.call(this, ...args);
                    //更新last
                    last = Date.now()
                }
            }
        }
    </script>
</body>

总结

防抖节流都是通过控制函数执行的频率来优化性能,但是二者原理不同,防抖是用户在规定的时间内没有第二次的操作才执行逻辑,如果用户一直点击,则逻辑不会执行.节流在规定的时间内这个逻辑最多只能执行一次,用户一直点击,则逻辑会在每次规定时间到达后执行