js 函数节流 函数防抖

字数 217阅读 59

一、函数节流throttle

  • 主要功能: 在 wait 秒内最多执行 func 一次的函数。
  • 常用场景
    1. 计算鼠标移动的距离(mousemove)
    2. Canvas 模拟画板功能(mousemove)
    3. 游戏的 mousedown/keydown 事件(单位时间只触发一次攻击)
    4. scroll事件
  • 基本实现:
export default function throttle(fn, threshhold = 250, scope) {
  let last;
  let deferTimer;

  return function () {
    let context = scope || this;
    let now = +new Date;
    let args = arguments;
    if (last && now < last + threshhold) {
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        last = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      last = now;
      fn.apply(context, args);
    }
  };
}

二、 函数防抖 debounce

  • 主要功能:频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。

  • 常用场景: onChange、mouseEnter、resize等事件

  • 原理: 通过闭包保存一个标记来保存 setTimeout 返回的值,每当事件调用防抖函数时如果没有超过指定时间间隔则把前一个 setTimeout clear 掉,然后又创建一个新的 setTimeout。如果超过指定时间间隔则调用事件任务

  • 基本实现

export default function debounce(func, wait, immediate) {
  let timeout;
  let args;
  let context;
  let timestamp;
  let result;

  const later = function later() {
    const last = +(new Date()) - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) {
          context = null;
          args = null;
        }
      }
    }
  };

  return function debounced() {
    context = this;
    args = arguments;
    timestamp = +(new Date());

    const callNow = immediate && !timeout;
    if (!timeout) {
      timeout = setTimeout(later, wait);
    }

    if (callNow) {
      result = func.apply(context, args);
      context = null;
      args = null;
    }

    return result;
  };
}

推荐阅读更多精彩内容