Skip to content

三、防抖

快速开始

基础防抖函数

这是最通用的实现方式,利用闭包保存定时器。如果在等待时间内再次触发,则清除之前的定时器。

javascript
function debounce(fn, delay) {
  let timer = null; // 闭包保存定时器
  
  return function(...args) {
    // 取消上一次的任务
    if (timer) clearTimeout(timer);
    
    // 重新设置定时器
    timer = setTimeout(() => {
      fn.apply(this, args); // 确保 this 指向正确
    }, delay);
  };
}

// 使用示例
const input = document.querySelector('input');
const search = (e) => console.log('搜索:', e.target.value);

input.addEventListener('input', debounce(search, 500));

立即执行版

有时候我们需要在触发事件的第一次立即执行函数(例如用户快速点击按钮),而不是等待延迟。

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

  return function(...args) {
    const callNow = immediate && !timer; // 判断是否立即执行

    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      timer = null; // 延迟结束后清空 timer,允许下次立即执行
    }, delay);

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

// 使用示例:按钮防抖,第一次点击立即生效,500ms 内再次点击无效
const btn = document.querySelector('button');
const submit = () => console.log('提交表单');

btn.addEventListener('click', debounce(submit, 500, true));

使用 Lodash 库

如果你项目中已经引入了 Lodash,直接使用它的 _.debounce 是最稳妥、兼容性最好的方案,它还提供了 cancelflush 方法。

javascript
// 假设已引入 lodash
// import _ from 'lodash';

const handleResize = () => console.log('窗口调整完毕');

// 创建防抖函数
const debouncedResize = _.debounce(handleResize, 300);

window.addEventListener('resize', debouncedResize);

// 高级用法:立即取消防抖并执行
// debouncedResize.flush();