JS防抖和节流的本质

86 阅读1分钟

防抖 debounce

函数防抖就是在函数需要频繁触发的情况下,只有足够的空闲时间,才执行一次。

典型应用

  • 百度搜索框在输入稍有停顿时才更新推荐热词。
  • 拖拽
function debounce(handler, delay){

  delay = delay || 300;
  var timer = null;

  return function(){

    var _self = this,
        _args = arguments;

    clearTimeout(timer);
    timer = setTimeout(function(){
      handler.apply(_self, _args);
    }, delay);
  }
}

防抖函数为什么要记录this和参数的例子: debounce-demo.js

节流 throttle

一个函数只有在大于执行周期时才执行,周期内调用不执行。好像水滴积攒到一定程度才会触发一次下落一样。

典型应用:

  • 抢券时疯狂点击,既要限制次数,又要保证先点先发出请求
  • 窗口调整
  • 页面滚动
function throttle(handler, wait){

  wait = wait || 300;
  var lastTime = 0;

  return function(){
    var _self = this,
    _args = arguments;

    var nowTime = new Date().getTime();
    if((nowTime - lastTime) > wait){
      handler.apply(_self, _args);
      lastTime = nowTime;
    }
  }
}

复杂但好用版:

function throttle(fn, interval, context, firstTime) {
  let timer;
  firstTime = typeof firstTime !== 'undefined' ? firstTime : true;
  return function() {
    let args = arguments;
    let __me = this;
    if (typeof context !== 'undefined') {
      __me = context;
    }

    if (firstTime) {
      fn.apply(__me, args);
      return (firstTime = false);
    }

    if (timer) {
      return false;
    }

    timer = setTimeout(function() {
      clearTimeout(timer);
      timer = null;

      fn.apply(__me, args);
    }, interval);
  };
}

节流与防抖的本质

以闭包的形式存在,通过对事件对应的回调函数进行包裹、以自由变量的形式缓存时间信息,最后用定时器时间差来控制事件的触发频率。

image.png