JS函数的防抖和节流

防抖:debounce,禁止反弹。 节流:throttle,也就是减速的意思。

  • 防抖用于:不频繁触发事件,即短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。
  • 节流用于:连续触发事件,但在 n 秒内只执行一次函数。即 2n 秒内执行 2 次… 。节流如字面意思,会稀释函数的执行频率。

防抖有两类用法,立即执行+非立即执行。

  • 非立即执行:触发事件后函数不立即执行,而是在 n 秒后执行。如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
  • 立即执行:触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
/**
   * @desc 函数防抖
   * @param func 目标函数
   * @param wait 延迟执行毫秒数
   * @param immediate true - 立即执行, false - 延迟执行
   */
function debounce(func, wait, immediate) {
    let timer;
    return function() {
      let context = this,
          args = arguments;
           
      if (timer) clearTimeout(timer);
      if (immediate) {
        let callNow = !timer;
        timer = setTimeout(() => {
          timer = null;
        }, wait);
        if (callNow) func.apply(context, args);
      } else {
        timer  = setTimeout(() => {
          func.apply
        }, wait)
      }
    }
}

节流也有两大类:时间戳+定时器

  • 时间戳:在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。
  • 定时器:在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次,在停止触发事件后,函数还会再执行一次。
  • 两类节流函数的区别:时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
/**
 * @desc 函数节流
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param type 1 表时间戳版,2 定时器版
 */
function throttle(func, wait, type) {
  if (type === 1) {
    let previous = 0;
  } else if (type === 2) {
    let timeout;
  }
  return function() {
    let context = this;
    let args = arguments;
    if (type === 1) {
        let now = Date.now();
 
        if (now - previous > wait) {
          func.apply(context, args);
          previous = now;
        }
    } else if (type === 2) {
      if (!timeout) {
        timeout = setTimeout(() => {
          timeout = null;
          func.apply(context, args)
        }, wait)
      }
    }
  }
}