JavaScript中的防抖Debounce和节流Throttle

avatarplhDigital nomad

前言

被问了无数次了

节流Throttling

通常用于滚动事件,scroll,touchmove事件。在ms时间内只能执行一次,那我要特么怎么知道上一次函数有没有执行完毕。通过now - lastTime>ms得知。目前测试没有bug

function throttle(callback, ms){
  var times;
  var last = 0;
  var outArgs = arguments
  return function (){
    var innerArgs = arguments
    var now = +new Date();
    if(now>last+ms){
      // 超过节流时间,执行一次,并将上次执行时间戳更新。
      last = now
      callback.apply(this,[...innerArgs, ...[...outArgs].splice(2,)]);
    }
  }
}

防抖Debouncing

通常用于resize,这个陌生,但是点击按钮添加防抖总听过了吧,为了防止某些脑残用户不断点击提交按钮,持续触发onclick事件,导致JavaScript报错。原生js实现方式,,这个特别简单。

function debounce(callback, ms){
  var times;
  var outArgs = arguments
  return function (){
    var self = this
    var innerArgs = arguments
    clearTimeout(times)  // 如果你在某段时间之内再次触发,清除上一次触发的定时器,重新添加定时器。
    times = setTimeout (function () {
      callback.apply(self,[...innerArgs, ...[...outArgs].splice(2,)]);
    },ms)
  }
}

上述函数有两个非常有意思地点:

  • 闭包垃圾回收机制,times属于返回函数引用地外部变量,这个时候外部变量被返回函数引用,导致无法触发JavaScript地垃圾回收机制,这样子,每次函数被调用,都会共享之前的timer变量,除非你将debounce函数重新执行一次,不然times变量依然是之前那个,垃圾回收机制被禁止触发,因为times变量地引用次数>0,

  • 事件代理函数只接受一个未执行函数func,而不接受已执行函数。func(),同时接受返回的未执行函数,并为该函数提供event参数。

document.addEventListener('click',actionFunc(1,2,3))   // 无法触发事件代理模型
document.addEventListener('click',actionFunc)    // 成功触发事件代理。