什么是防抖

防止在规定时间内不断触发的操作;

逻辑流程为:
触发操作;
进入规定时间内的倒计时;
如果在倒计时内再次触发,则重新开始倒计时;
倒计时结束,执行操作;

使用场景:用户输入验证、联想搜索、浏览器缩放检测…


什么是节流

一定时间内只执行一次操作;

逻辑流程为:
触发操作;
进入规定时间内的倒计时;
如果在倒计时内再次触发,则忽略再次触发的操作;
倒计时结束,执行最初的操作;

使用场景:监听浏览器滚动、连续点击按钮、弹幕刷新…


防抖函数

/**
 * 函数防抖
 *
 * @param {function} func 函数
 * @param {number} wait 延迟执行毫秒数
 * @param {boolean} immediate true 表立即执行; false 表非立即执行
 * 
 * @return {function} 任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
 */
var T_DEBOUNCE = (func, wait, immediate) => {
  let timeout;
  return function() {
    let context = this;
    let args = arguments;

    if (timeout) clearTimeout(timeout);
    if (immediate) {
      let callNow = !timeout;
      timeout = setTimeout(() => {
        timeout = null;
      }, wait);
      if (callNow) {
        func.apply(context, args);
      };
    } else {
      timeout = setTimeout(() => {
        func.apply(context, args)
      }, wait);
    };
  };
};

节流函数

/**
 * 函数节流
 *
 * @param {function} func 函数
 * @param {number} wait 延迟执行毫秒数
 * @param {number} type 1 表时间戳版; 2 表定时器版
 * 
 * @return {function} 指定时间间隔内只会执行一次任务
 */
var T_THROTTLE = (func, wait, type) => {
  let previous, timeout;
  if (type === 1) {
    previous = 0;
  } else if (type === 2) {
    timeout = null;
  };

  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);
      };
    };
  };
};