标准答案

  1. 防抖 debounce 的核心是每次触发都清理旧定时器,并重新计时。
  2. 节流 throttle 的核心是在一段时间内限制执行频率。
  3. 防抖关注最后一次,节流关注固定频率。
  4. 实现时要透传 this 和参数,否则事件回调或对象方法会出问题。
  5. 完整版本还可以支持立即执行、取消执行和尾部执行。

题目解析

防抖和节流都处理高频触发,但业务含义不同。搜索框输入中间态通常不需要请求,所以适合防抖;滚动位置需要持续反馈,只是不能太频繁,所以适合节流。

手写实现不能只写 setTimeout。真实回调常依赖事件对象、当前 this 和最新参数,这些都需要从包装函数传进去。

组件卸载时还要清理定时器。否则延迟执行的回调可能在页面离开后继续修改状态,造成警告或脏数据。

代码示例

基础版本先覆盖延迟执行、固定频率、this 和参数透传。

JavaScript
function debounce(fn, delay) {
  let timer = null

  return function debounced(...args) {
    clearTimeout(timer)

    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

function throttle(fn, wait) {
  let lastTime = 0

  return function throttled(...args) {
    const now = Date.now()

    if (now - lastTime >= wait) {
      lastTime = now
      fn.apply(this, args)
    }
  }
}

常见误区

  • 把防抖和节流的适用场景说反。
  • 只写定时器逻辑,忘记透传 this 和参数。
  • 组件卸载或页面离开时没有清理未执行的防抖回调。

作者信息