关键词

浅谈JavaScript节流和防抖函数

浅谈JavaScript节流和防抖函数

前言

在前端开发中,我们经常会遇到需要监听用户操作并执行相应任务的情况,例如用户在搜索框中输入关键词时,会实时通过ajax请求获取匹配结果;用户在滚动页面时,会自动加载更多的内容等等。但是由于用户的操作往往不可预测,当用户频繁进行操作时,会导致一些性能问题,如频繁地发送请求,重复执行相同的逻辑等等。这时候,就需要用到节流和防抖函数来限制这种不必要的操作。

节流函数(throttle)

节流函数是指在一段时间内,只执行一次事件。它可以避免一些高频率调用的事件,使其被间隔执行。常见的节流函数有时间戳版本和定时器版本。时间戳版本即指在固定时间内执行一次时间函数,而定时器版本则是在固定时间后执行一次事件。

以定时器版本为例,其基本模板代码为:

function throttle(func, delay) {
  let canRun = true;
  return function() {
    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      func.call(this, ...arguments);
      canRun = true;
    }, delay);
  };
}

在上述代码中,canRun表示此时函数能否执行的标志,在未达到规定时间时,其为false,在达到规定时间后,其变为true,以便下一次可以执行函数。在函数执行前将canRun标记为false,并将当次执行函数的参数延迟到delay后才执行。 这才是节流执行的精髓所在。

接下来,我们来看一个实例,通过点击一次按钮打印当前时间,并且确保在一定时间间隔内只执行一次。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>throttle示例</title>
  </head>
  <body>
    <button id="btn">点击弹出当前时间</button>
    <script>
      function throttle(func, delay) {
        let canRun = true;
        return function () {
          if (!canRun) return;
          canRun = false;
          setTimeout(() => {
            func.call(this, ...arguments);
            canRun = true;
          }, delay);
        };
      }
      let clickHandler = throttle(function () {
        console.log(new Date().toLocaleTimeString());
      }, 1000);
      document.getElementById('btn').addEventListener('click', clickHandler);
    </script>
  </body>
</html>

在上述示例中,当我们点击按钮后,函数会在1秒后输出当前时间,即使我们快速点击多次,也只会在1秒后输出最后一次操作的时间。

防抖函数(debounce)

防抖函数也是用于避免函数的重复执行,但是相比节流函数,它是在每次事件结束后规定时间再执行事件,而不是固定时间内只执行一次事件。这样,在函数执行后,如果用户继续操作,则计时器被清空,重新规定事件。

以定时器版本为例,其基本模板代码为:

function debounce(func, delay) {
  let timer = null;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.call(this,...arguments);
    },delay);
  };
}

在上述代码中,timer表示setTimeout函数的返回值,在每次函数执行前清除上次setTimeout事件,调用最新的setTimeout事件来执行新的函数。调用方法如下:

let debouncedFunc = debounce(function () {
  console.log(new Date().toLocaleTimeString());
}, 1000);

接下来,我们来看一个实例,限制滚动事件每500ms触发一次:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>debounce示例</title>
  </head>
  <body>
    <div style="height: 2000px"></div>
    <script>
      function debounce(func, delay) {
        let timer = null;
        return function () {
          clearTimeout(timer);
          timer = setTimeout(() => {
            func.call(this, ...arguments);
          }, delay);
        };
      }
      window.onscroll = debounce(function () {
        console.log(new Date().toLocaleTimeString());
      }, 500);
    </script>
  </body>
</html>

在上述示例中,当我们滚动页面时,函数会在500毫秒后输出当前时间,如果在500ms内连续滚动,只会在最后一次滚动结束后500ms输出时间。

总结

节流和防抖函数虽然在代码结构上十分相似,但是还是有一些区别的。防抖函数是在一定时间后执行事件,进行了时间避免错误,而节流函数则是规定在特定时间内只执行一次事件。在实际开发中,需要根据具体情况选择节流函数或防抖函数进行优化,从而减少对性能的影响。

本文链接:http://task.lmcjl.com/news/9108.html

展开阅读全文