【JavaScript】防抖和节流的原理是?区别是?如何实现?

防抖

防抖的定义:

防抖 ( debounce ):在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时(本质是一个定时器)。

防抖的应用场景:

例如:

  1. input 事件,搜索框的联想功能,不断输入值的时候,使用防抖来节约资源;
  2. 短信验证码;
  3. 提交表单;
  4. resize 事件;

防抖的实现:

      function debounce(fn) {
        let that = this;
        let timeout = null;
        // 创建一个标记用来存放定时器的返回值
        return function () {
          clearTimeout(timeout);
          // 每当用户输入的时候把前一个 setTimeout clear 掉
          timeout = setTimeout(() => {
            // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
            fn.apply(that, arguments);
          }, 500);
        };
      }
      function sayHello() {
        console.log("防抖成功");
      }
      var inp = document.getElementById("inp");
      inp.addEventListener("input", debounce(sayHello)); // 防抖

节流

节流的定义

节流 ( throttle ):规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

节流的应用场景:

  1. scroll 事件,单位时间后计算一次滚动位置;
  2. input 事件,实现实时关键字查找;
  3. 播放事件,计算进度条;

节流的实现:

      function throttle(fn) {
        const that = this;
        let canRun = true; // 通过闭包保存一个标记
        return function () {
          if (!canRun) return;
          // 在函数开头判断标记是否为 true,不为 true 则 return
          canRun = false; // 立即设置为 false
          setTimeout(() => {
            // 将外部传入的函数的执行放在 setTimeout 中
            fn.apply(that, arguments);
            // 最后在 setTimeout 执行完毕后再把标记设置为 true(关键) 表示可以执行下一次循环了。当定时器没有执行的时候标记永远是 false,在开头被 return 掉
            canRun = true;
          }, 500);
        };
      }
      function sayHello(e) {
        console.log(e.target.innerWidth, e.target.innerHeight);
      }
      window.addEventListener("resize", throttle(sayHello));

防抖和节流的区别:

1、函数防抖和函数节流都是防止某一时间频繁触发,但是这两兄弟之间的原理却不一样。
2、函数防抖是某一段时间内只执行一次,而函数节流是单位时间执行一次。

防抖和节流在实际工作的时候一般使用lodash插件内置的函数实现。

如有不同见解,欢迎讨论,更多内容,正在更新中。。。。。。

猜你喜欢

转载自blog.csdn.net/leoxingc/article/details/127910781