logo
AI对话
AI写作
AI学术
AI绘画
知识社区

如何实现防抖函数提升网页性能与用户体验

此对话是使用 海鲸AI 创建的 • 发布时间:2026年05月11日 21:27

帮我写个防抖函数

复制问题

防抖函数(Debounce)的作用是触发事件后延迟n秒执行回调,如果在n秒内再次触发,则重新计时,常用于搜索框输入、窗口 resize 等场景。以下是几种常见语言的实现:

1. JavaScript 防抖函数

最经典的实现,支持立即执行和取消功能:

function debounce(fn, delay, immediate = false) {
  let timer = null; // 定时器缓存
  return function(...args) {
    // 清除之前的定时器
    if (timer) clearTimeout(timer);
    
    // 立即执行(首次触发时执行)
    if (immediate && !timer) {
      fn.apply(this, args);
    }
    
    // 重新设置定时器
    timer = setTimeout(() => {
      if (!immediate) {
        fn.apply(this, args); // 非立即执行时,延迟后调用
      }
      timer = null; // 执行后清空定时器
    }, delay);
  };
}

// 使用示例
const searchInput = document.getElementById('search');
const handleSearch = debounce((e) => {
  console.log('搜索内容:', e.target.value);
}, 500); // 500ms防抖

searchInput.addEventListener('input', handleSearch);

2. Python 防抖函数

基于装饰器实现,适用于按钮点击、输入事件等:

import time
from functools import wraps

def debounce(delay, immediate=False):
    def decorator(fn):
        last_call = 0  # 上次调用时间
        @wraps(fn)
        def wrapper(*args, **kwargs):
            nonlocal last_call
            now = time.time()
            # 计算距离上次调用的时间差
            if now - last_call < delay:
                last_call = now
                return  # 未满足延迟,不执行
            # 立即执行(首次触发)
            if immediate and last_call == 0:
                result = fn(*args, **kwargs)
                last_call = now
                return result
            # 延迟执行
            last_call = now
            # 使用定时器(Python中需手动处理,这里简化为直接延迟)
            # 实际场景可结合 threading.Timer
            time.sleep(delay)
            return fn(*args, **kwargs)
        return wrapper
    return decorator

# 使用示例
@debounce(delay=0.5, immediate=True)  # 0.5秒防抖
def handle_search(keyword):
    print(f"搜索: {keyword}")

handle_search("Python")  # 立即执行
handle_search("Java")    # 0.5秒内触发,被防抖

3. TypeScript 防抖函数

带类型定义,更严谨:

type DebounceFn = (...args: any[]) => void;

function debounce<T extends DebounceFn>(
  fn: T,
  delay: number,
  immediate: boolean = false
): T {
  let timer: NodeJS.Timeout | null = null;
  return function (this: any, ...args: Parameters<T>) {
    if (timer) clearTimeout(timer);
    if (immediate && !timer) {
      fn.apply(this, args);
    }
    timer = setTimeout(() => {
      if (!immediate) {
        fn.apply(this, args);
      }
      timer = null;
    }, delay);
  } as T;
}

// 使用示例
const handleResize = debounce(() => {
  console.log('窗口大小变化:', window.innerWidth);
}, 300);

window.addEventListener('resize', handleResize);

核心逻辑总结

  1. 定时器缓存:用变量记录当前定时器,重复触发时清除旧定时器。
  2. 延迟执行:每次触发后重新设置定时器,延迟 delay 毫秒执行目标函数。
  3. 立即执行选项:immediate: true 时,首次触发立即执行,后续触发防抖。
  4. this 绑定:通过 apply/call 确保函数执行时的上下文正确。

应用场景

  • 搜索框实时联想(避免输入过程中频繁请求接口)
  • 窗口大小调整(resize 事件防抖)
  • 按钮点击防重复提交
  • 滚动加载(scroll 事件防抖)

根据具体需求选择语言版本,JavaScript/TypeScript 版本在前端开发中最常用~

语音播放
复制回答