一天一题:聊聊前端的防抖与节流

290 阅读3分钟

什么是防抖与节流?

防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。使用场景举例:每次 resize/scroll 触发统计事件 、 按钮点击事件等

节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。使用场景举例:DOM 元素的拖拽功能实现(mousemove)、计算鼠标移动的距离(mousemove)、onScoll

防抖的实现

实现思路如下,将目标方法(动作)包装在setTimeout里面,然后这个方法是一个事件的回调函数,如果这个回调一直执行,那么这些动作就一直不执行。为什么不执行呢,我们搞了一个clearTimeout,这样setTimeout里的方法就不会执行!为什么要clearTimeout呢,我们就需要将事件内的连续动作删掉嘛!待到用户不触发这事件了。那么setTimeout就自然会执行这个方法。

这个方法的重点是,它在用户不触发事件的时,才触发动作,并且抑制了本来在事件中要执行的动作。

  // 防抖
  function debounce(fn, wait) {
      var timeout = null;
      return function() {
          if(timeout !== null)   clearTimeout(timeout);
          timeout = setTimeout(fn, wait);
      }
  }
  // 处理函数
  function handle() {
      console.log(Math.random());
  }
  // 滚动事件
  window.addEventListener('scroll', debounce(handle, 1000));

当持续触发scroll事件时,事件处理函数handle只在停止滚动1000毫秒之后才会调用一次,也就是说在持续触发scroll事件的过程中,事件处理函数handle一直没有执行。

节流的实现

节流的概念可以想象一下水坝,你建了水坝在河道中,不能让水流动不了,你只能让水流慢些。换言之,你不能让用户的方法都不执行。如果这样干,就是debounce了。为了让用户的方法在某个时间段内只执行一次,我们需要保存上次执行的时间点与定时器。

简单的总结一下就是:限制一个函数在一定时间内只能执行一次。

函数节流主要有两种实现方法:时间戳和定时器。接下来分别用两种方法实现throttle

节流throttle代码(时间戳):

  //节流throttle代码(时间戳)
  var throttle = function(func, delay) {
    var prev = Date.now();
    return function() {
      var context = this;
      var args = arguments;
      var now = Date.now();
      if (now - prev >= delay) {
        func.apply(context, args);
        prev = Date.now();
      }
    }
  }
  //处理函数
  function handle() {
    console.log(Math.random());
  }
  //滚动事件
  window.addEventListener('scroll', throttle(handle, 1000));

节流throttle代码(定时器):

 // 节流throttle代码(定时器):
 var throttle = function(func, delay) {
     var timer = null;
     return function() {
         var context = this;
         var args = arguments;
         if (!timer) {
             timer = setTimeout(function() {
                 func.apply(context, args);
                 timer = null;
             }, delay);
         }
     }
 }
 //处理函数
 function handle() {
     console.log(Math.random());
 }
 //滚动事件
 window.addEventListener('scroll', throttle(handle, 1000));