JS的防抖函数与节流函数区别以及用法

414 阅读4分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

大家好,我是 摸鱼小公举,真正的强者,不会怨天尤人,如果想不被别人看轻,你就只有付出比别人多十倍百倍的努力,才能站的比别人更高。上一篇文章是 reduce的11种用法,文章内容是关于reduce的11种用法。那么今天我们来学习一下防抖函数和节流函数。

防抖函数(debounce)(连续一直点击直到松开只会执行一次)

概念

防抖函数就是指触发事件后,在 n 秒内函数只能执行一次,如果;触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

在前端开发的时候,有些事件会被频繁调用(onresize,scroll,mousemove,mousehover ), 甚至短时间内多次触发。如果不作限制,有的可能一秒之内执行几十次甚至上百次,如果 这些函数内部还执行了其它函数,特别是执行操作DOM函数,浏览器将很好性能,甚至 造成浏览器卡死的情况,这是很致命的问题;还要短时间内多次调用接口,不仅造成数 据关系混乱还会造成网络堵塞,增加服务器的压力。这个问题也是需要优化的。

debounce使用场景

  1. scroll事件(资源的加载)
  2. mousemove事件(拖拽)
  3. resize事件(响应式布局样式)
  4. keyup事件(输入框文字停止打字后才进行校验)

debounce方法

 function debounce(fn, delay) {
    var ctx;
    var args;
    var timer = null;
    var later = function () {
      fn.apply(ctx, args);
      // 当事件真正执行后,清空定时器
      timer = null;
    };
    return function () {
      ctx = this;
      args = arguments;
      // 当持续触发事件时,若发现事件触发的定时器已设置时,则清除之前的定时器
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      // 重新设置事件触发的定时器
      timer = setTimeout(later, delay);
    };
  }

首先我来给大家示范一个错误的调用

HTML代码
<div id="box">连续点击(防抖)</div>
<div id="box1">连续点击(节流)</div>
<div id="echo"><input type="text" onkeyup="inputKey()" /></div>

JS代码
//具名函数
function inputKey() {
  this.debounce(function () {
  console.log("输入点击了");
  }, 1000);  
  }

来看一下效果,按照上面所说,用了防抖函数会执行一次函数打印出东西,现在是没效果

fangdou.gif

我们来看一下正确的调用方法吧,在这里我只能说具名函数调用防抖和节流的函数无效。

//等于号后面只能调用别人的方法或者声明一个匿名函数
 document.getElementById("keys").onkeyup = throttle((e) => {
    console.log(e, "111111防抖");
 }, 500);

效果真的跟上面说的一样完美

jieliu1.gif

节流函数

概念

节流函数会延迟执行一个函数,当重复调用函数的时候,每隔延迟毫秒就会调用一次函数。它会减少多次调用函数的频率。

throttle使用场景 (一直点击在几秒之内就会自动执行一次)

  1. click事件(不停快速点击按钮,减少触发频次)
  2. scroll事件(返回顶部按钮出现\隐藏事件触发)
  3. keyup事件(输入框文字与显示栏内容复制同步)
  4. 减少发送ajax请求,降低请求频率

throttle方法

  function throttle(fn, delay) {
    var timer = null;
    var timeStamp = new Date();
    return function () {
      var context = this; //获取函数所在作用域this
      var args = arguments; //取得传入参数
      if (new Date() - timeStamp > delay) {
        timeStamp = new Date();
        timer = setTimeout(function () {
          fn.apply(context, args);
        }, delay);
      }
    };
  }

调用throttle方法如下

  document.getElementById("keys").onkeyup = throttle((e) => {
    console.log(e, "111111节流");
  }, 1000);
  

效果完美

fangdou3.gif

在n秒内快速点击几下效果是看不出有什么差别,只有点击超过那几秒的范围才会看到防抖和节流函数的差别

类似节流函数的一个方法

此方法与上面两个函数不一样的是,该函数一开始就触发,之后每隔几秒会调用一次

  function preventDuplicateClicks(timeLengtn) {
    //跟button设置disable差不多的逻辑
    if (!this.isClick) {
      this.isClick = true;
      setTimeout(() => {
        this.isClick = false;
      }, timeLengtn);
      return false;
    } else {
      return true;
    }
  }

调用方法如下,跟上面不一样的是这里可以用具名函数来调用

HTML代码
 <div id="box">连续点击(防抖)</div>
 <div id="box1">连续点击(节流)</div>
 <div id="echo"><input id="keys" type="text" onkeyup="inputKey()" /></div>

JS代码
  function inputKey() {
    if (this.preventDuplicateClicks(2000)) {
      return false;
    }
    console.log("输入点击了");
  }

效果如下

jieliu2.gif

此方法也可用于减少多次调用事件的频率

结语

好了文章到这就结束了,欢迎大家( 点赞+评论+关注 ) 有问题可以来互相交流一下;希望这篇文章对大家有用,也希望大家多多支持我。 今天是我参与2022首次更文挑战的第7天,加油!