如何实现一个防抖函数?

如何在项目中实现一个防抖函数?

阅读 542
avatarAI BotBETA

JavaScript防抖实现方案:

function debounce(func, wait = 300, immediate = false) {
  let timeout

  return function executedFunction(...args) {
    const context = this
    const later = () => {
      timeout = null
      if (!immediate) func.apply(context, args)
    }

    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)

    if (callNow) func.apply(context, args)
  }
}

核心特性:

  1. 延迟执行:事件触发后等待指定时间(wait)才执行
  2. 重置计时:连续触发会不断重置倒计时
  3. 立即执行模式:immediate=true时首次触发立即执行
  4. 参数传递:保留事件参数和this上下文

使用示例:

// 输入框搜索建议
const searchInput = document.querySelector('#search')
const fetchSuggestions = debounce((query) => {
  console.log('发起请求:', query)
}, 500)

searchInput.addEventListener('input', (e) => fetchSuggestions(e.target.value))

// 窗口resize监听
window.addEventListener('resize', debounce(() => {
  console.log('窗口尺寸稳定后执行')
}, 200))

实现要点:

  1. 使用闭包保存定时器标识
  2. 通过apply方法保持原始函数的上下文
  3. 支持配置是否立即执行
  4. 通过剩余参数(...args)传递原始事件参数

与节流(throttle)的区别:
防抖关注最后一次触发后的延迟执行,而节流保证固定时间间隔最多执行一次。根据场景需求选择合适方案。

2 个回答
/**
 * 防抖函数
 * @param {Function} fn - 需要防抖的函数
 * @param {number} delay - 延迟时间(毫秒)
 * @param {boolean} immediate - 是否立即执行
 * @return {Function} - 防抖处理后的函数
 */
function debounce(fn, delay = 300, immediate = false) {
  let timer = null;
  
  return function(...args) {
    // 保存this上下文
    const context = this;
    
    // 如果已经设定过定时器,则清空上一次的定时器
    if (timer) clearTimeout(timer);
    
    // 如果是立即执行且当前没有定时器
    if (immediate && !timer) {
      fn.apply(context, args);
    }
    
    // 设置新的定时器
    timer = setTimeout(() => {
      if (!immediate) {
        fn.apply(context, args);
      }
      // 执行完后清空定时器
      timer = null;
    }, delay);
  };
}

防抖(Debounce)是一种优化技术,用于限制函数在短时间内多次触发。

示例代码

function debounce(func, delay) {
    let timer;
    return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
            func.apply(this, args);
        }, delay);
    };
}
window.addEventListener('resize', debounce(() => {
    console.log('Window resized');
}, 300));

口语化解释:防抖函数会在事件触发后等待一段时间,如果在这段时间内事件再次触发,则重新计时。这样可以避免频繁触发函数,比如在窗口调整大小时。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题