# 实现 debounce (函数防抖)

事件停止触发后 n 秒才执行函数一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

# 使用场景

  • 浏览器窗口的 resize 事件
    • 计算窗口大小
  • 拖拽时的 mousemove 事件
  • 键盘事件 keyup、input、click
    • 用户名、手机号、邮箱是否已存在验证
    • 输入框远程搜索
    • 防止表单重复提交

# 代码实现

# 👩‍💻:technologist: 简单版

/**
 * 简单版
 * @param {Function} func 函数
 * @param {Number} wait 等待时间
 */
function debounce(func, wait) {
  let timer
  return function () {
    clearTimeout(timer)
    timer = setTimeout(() => {
      func.apply(this, arguments)
    }, wait)
  }
}

# 👩‍💻:technologist: 立即执行

提示: 立即执行是指,不希望等到事件停止触发后才执行,希望立刻执行函数,然后等到停止触发 n 秒后,才可以重新触发执行。

/**
 * 有头无尾 & 无头有尾
 * @param {Function} func 函数
 * @param {Number} wait 等待时间
 * @param {Boolean} immediate 是否立即执行
 */
function debounce (func, wait, immediate) {
  let timer, result
  const debounced = function () {
    if (timer) clearTimeout(timer)

    if (immediate) { // 立即执行
     // 如果已经执行过,timer 不为 null,func 不再执行,只有当停止事件触发 wait 秒后,
     //   timer 重新为 null,才会再次执行 func
      const callNow = !timer
      timer = setTimeout(() => {
        timer = null
      }, wait)
      if (callNow) result = func.apply(this, arguments)
    } else {
      timer = setTimeout(() => {
        func.apply(this, arguments)
      }, wait)
    }

    return result
  }

  debounced.cancel = function () { // 取消
    clearTimeout(timer)
    timer = null
  }

  return debounced
}

# 参考: