节流和防抖

节流和防抖的作用都是防止函数多次调用。区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于设置的时间,防抖的情况下只会调用一次,而节流的情况会每隔一定时间调用一次函数。
防抖(debounce): n秒内函数只会执行一次,如果n秒内高频时间再次被触发,则重新计算时间。

function debounce(func, wait, immediate = true) {
  let timeout, context, args;
  // 延迟执行函数
  const later = () => setTimeout(() => {
    // 延迟函数执行完毕,清空定时器
    timeout = null
    // 延迟执行的情况下,函数会在延迟函数中执行
    // 使用到之前缓存的参数和上下文
    if(!immediate) {
      func.apply(context, args);
      context = args = null;
    }
  }, wait);
  let debounced = function (...params) {
    if(!timeout) {
      timeout = later();
      if(!immediate) {
        // 立即执行
        func.apply(this, params);
      } else {
        // 闭包
        context = this;
        args = params;
      }
    } else {
      clearTimeout(timeout);
      timeout = later();
    }
  }
  debounced.cancel = function () {
    clearTimeout(timeout);
    timeout = null;
  }
  return debounced;
};

防抖的应用场景

· 每次resize/scroll触发统计时间;
· 文本输入的验证(连续输入文字后发送AJAX请求进行验证,验证一次就好)


节流(throttle): 高频时间在规定时间内只会执行一次,执行一次后,只有大于设定的执行周期后才会执行第二次。

function throttle(func, wait, options) {
  var timeout, context, args, result;
  var previous = 0;
  if(!options) options = {};
  var later = function () {
    previous = options.leading === false ? 0 : Date.now() || new Date().getTime();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout)  context = args = null;
  };
  var throttled = function () {
    var now = Date.now() || new Date().getTime();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      // 判断是否设置了定时器和trailing
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
  throttled.cancel = function () {
    clearTimeout(timeout);
    previous = 0;
    timeout = context = args = null;
  };
  return throttled;
};

节流的应用场景

· DOM元素的拖拽功能实现(mousemove)
· 射击游戏的mousedown/keydown事件(单一时间内只能发射一枚子弹)
· 计算鼠标移动的距离(mousemove)
· Canvas模拟画板功能(mousemove)
· 搜索联想(keyup)
· 监听滚动事件判断是否到页面底部自动加载更多:给scroll加了debounce后,只有用户停止滚动后,才会判断是否到了页面底部;如果是throttle的话,只要页面滚动就会间隔一段时间判断一次。

你可能感兴趣的:(节流和防抖)