防抖节流

49 阅读1分钟
/**
 * 防抖函数
 * @param {Function} func 需要防抖的函数
 * @param {number} wait 等待时间(毫秒)
 * @param {boolean} [immediate=false] 是否立即执行
 * @returns {Function} 防抖后的函数
 */
const debounce = (func, wait, immediate = false) => {
  let timeout = null;
  let shouldInvoke = immediate; // 函数是否可以执行

  return function (...args) {
    const context = this;

    if (shouldInvoke) {
      func.apply(context, args);
      shouldInvoke = false;
    }

    if (timeout) {
      clearTimeout(timeout);
    }

    timeout = setTimeout(() => {
      if (!immediate) func.apply(context, args);
      shouldInvoke = immediate;
    }, wait);
  };
};

/**
 *
 * @param {*} fn 函数
 * @param {*} time 时间间隔
 * @param {*} immediately 是否立即执行
 * @param {*} last 最后一次是否执行
 * @returns
 */
const throttle = (fn, time, immediately = true, last = false) => {
  let imm = immediately; // 是否立即执行
  let flag = immediately; // 函数是否可以执行
  let timer = null; // 记录最后一次的定时器

  return function () {
    if (timer) {
      clearTimeout(timer);
    }
    const _this = this;
    if (flag) {
      // 如果函数可以执行
      fn.apply(_this, arguments);
      flag = false;
      setTimeout(() => {
        flag = true;
      }, time);
    } else {
      // 函数执行就不需要判断立即执行以及再把它当作最后一次,否则会造成重复执行!!!
      if (!imm) {
        // 如果不立即执行
        imm = true; // 保证后续按一般流程走
        setTimeout(() => {
          flag = true;
        }, time);
      }
      if (last) {
        // 如果最后一次需要执行,把每一次都假设为最后一次
        timer = setTimeout(() => {
          fn.apply(_this, arguments);
        }, time);
      }
    }
  };
};