跳到正文

手写练习/异步控制

GitHub

手写防抖 debounce

中等异步性能

代码实现

JavaScript22 行
function debounce(fn, delay, immediate = false) {
    let timer = null;

    return function (...args) {
        const context = this;
        const callNow = immediate && !timer;

        clearTimeout(timer);

        timer = setTimeout(() => {
            timer = null;

            if (!immediate) {
                fn.apply(context, args);
            }
        }, delay);

        if (callNow) {
            fn.apply(context, args);
        }
    };
}

笔记记录

手写防抖 debounce

是什么

防抖的规则是:高频事件持续触发时不执行,只有停止触发达到指定时间后才执行一次。

常见场景:

  • 搜索框输入后发起请求
  • 窗口尺寸变化后重新计算布局
  • 表单内容停止修改后自动保存

怎么执行

每次触发时都做两件事:

  1. 用 clearTimeout 取消上一个定时器。
  2. 重新创建一个 delay 毫秒后执行的定时器。

因此,只要事件在 delay 内再次到来,倒计时就会重新开始。

触发 A -> 创建定时器
触发 B -> 取消 A,创建新定时器
触发 C -> 取消 B,创建新定时器
停止触发 -> 等待 delay -> 执行 C 携带的回调

代码关键点

  • timer 保存在闭包里,多次调用会共享同一个定时器。
  • args 要传给 apply,不是未定义的 arg。
  • fn.apply(this, args) 保留调用时的 this 和参数。
  • 当 immediate 为 true 时,第一次触发会立即执行,后续触发仍会重置冷却时间。