JS的防抖和截流

Posted on 2021-02-26 12:19  我爱吃花椒  阅读(339)  评论(0编辑  收藏  举报
  • 转载
    防抖

     让某个函数在一定 事件间隔条件(去抖debounce) 或 时间间隔条件(节流throttle) 下才会去执行,避免快速多次执行函数(操作DOM,加载资源等等)给内存带来大量的消耗从而一定程度上降低性能问题。

     debounce: 当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

       debounce使用场景

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

     方法实现:

      

/**
 * 防反跳。fn函数在最后一次调用时刻的delay毫秒之后执行!
 * @param fn 执行函数
 * @param delay 时间间隔
 * @param isImmediate 为true,debounce会在delay时间间隔的开始时立即调用这个函数
 * @returns {Function}
 */
function debounce(fn, delay, isImmediate) {
  var timer = null;  //初始化timer,作为计时清除依据
  return function() {
    var context = this;  //获取函数所在作用域this
    var args = arguments;  //取得传入参数
    clearTimeout(timer);
    if(isImmediate && timer === null) {
        //时间间隔外立即执行
        fn.apply(context,args);
      timer = 0;
      return;
    }
    timer = setTimeout(function() {
      fn.apply(context,args);
      timer = null;
    }, delay);
  }
}

/* 方法执行e.g. */
var btn = document.getElementById('btn');
var el = document.getElementById('display');
var init = 0;
btn.addEventListener('click', debounce(function() {
  init++;
  el.innerText = init;
}, 1000,true));

  

  • 截流

     throttle:预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。

     throttle使用场景: 

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

    方法实现:

      

/**
 * 创建并返回一个像节流阀一样的函数,当重复调用函数的时候,最多每隔delay毫秒调用一次该函数
 * @param fn 执行函数
 * @param delay 时间间隔
 * @returns {Function}
 */
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);
    }

  }
}

/* 方法执行 */
var btn = document.getElementById('btn');
var el = document.getElementById('display');
var init = 0;
btn.addEventListener('click', throttle(function() {
  init++;
  el.innerText = init;
}, 1000));

  或者:

function throttle(fn, threshhold, scope) {
  threshhold || (threshhold = 250);
  var last,
    deferTimer;
  return function () {
    var context = scope || this;

    var now = +new Date(),
      args = arguments;
    if (last && now < last + threshhold) {
      // hold on to it
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        last = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      last = now;
      fn.apply(context, args);
    }
  };
}