怎样在JavaScript中实现防抖(debounce)?

来源:菜鸟站长作者:广州程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《怎样在JavaScript中实现防抖(debounce)?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《怎样在JavaScript中实现防抖(debounce)?》有用,将其分享出去将是对创作者最好的鼓励。

防抖(debounce)是JavaScript中处理高频触发事件的常用优化方案,核心思路是在事件触发后等待一段时间,如果这段时间内没有再次触发事件,才执行目标函数;如果再次触发,则重新计时。这种方式能避免函数在短时间内被多次执行,减少不必要的计算和资源消耗。

怎样在JavaScript中实现防抖(debounce)?

防抖的基础实现

最基础的防抖实现只需要利用定时器,每次触发事件时先清除之前的定时器,再重新设置新的定时器。下面是基础版本的代码:

function debounce(func, delay) {
  let timer = null;
  return function(...args) {
    // 清除之前的定时器,重新计时
    if (timer) clearTimeout(timer);
    // 设置新的定时器,delay时间后执行目标函数
    timer = setTimeout(() => {
      func.apply(this, args);
      timer = null;
    }, delay);
  };
}

这个版本的逻辑很清晰,返回的函数就是实际绑定到事件上的函数,每次调用时都会重置定时器,只有最后一次触发后等待delay时间没有新触发,才会执行func。

支持立即执行的防抖版本

有些场景下我们希望第一次触发事件时立即执行函数,之后在delay时间内再次触发则不执行,等delay时间过后再触发才会重新执行。这种需求可以通过添加一个是否立即执行的参数来实现:

function debounce(func, delay, immediate = false) {
  let timer = null;
  return function(...args) {
    if (timer) clearTimeout(timer);
    if (immediate) {
      // 判断是否已经有定时器,没有的话说明是第一次触发或者已经过了等待期
      const canExecute = !timer;
      // 设置定时器,用于重置执行状态
      timer = setTimeout(() => {
        timer = null;
      }, delay);
      // 可以执行的话立即调用目标函数
      if (canExecute) func.apply(this, args);
    } else {
      // 非立即执行版本,和之前的逻辑一致
      timer = setTimeout(() => {
        func.apply(this, args);
        timer = null;
      }, delay);
    }
  };
}

防抖与函数节流的区别

很多开发者会混淆防抖和函数节流,两者的核心差异在于执行时机:

  • 防抖是在事件停止触发后一段时间才执行,只执行最后一次触发的逻辑
  • 函数节流是在固定时间间隔内只执行一次,不管事件触发了多少次

可以通过下面的表格更直观地对比两者的差异:

特性防抖(debounce)函数节流(throttle)
执行时机事件停止触发后等待指定时间执行固定时间间隔执行一次
执行次数连续触发只执行最后一次连续触发按间隔执行多次
适用场景输入框搜索、表单验证、窗口resize适配滚动加载、鼠标移动拖拽、页面滚动监听

防抖的实际使用场景

输入框搜索场景

用户在输入框输入内容时,不需要每次输入都发送搜索请求,而是在用户停止输入一段时间后再发送,减少请求次数:

// 模拟搜索请求函数
function search(keyword) {
  console.log('发送搜索请求,关键词:', keyword);
}

// 创建防抖后的搜索函数,等待500毫秒执行
const debouncedSearch = debounce(search, 500);

// 获取输入框元素,绑定输入事件
const input = document.querySelector('input');
input.addEventListener('input', function(e) {
  debouncedSearch(e.target.value);
});

窗口resize适配场景

窗口大小改变时,不需要每次resize都重新计算布局,等用户调整完窗口大小后再执行适配逻辑:

// 布局适配函数
function adaptLayout() {
  console.log('执行布局适配,当前窗口宽度:', window.innerWidth);
}

// 创建防抖后的适配函数,等待300毫秒执行
const debouncedAdapt = debounce(adaptLayout, 300);

// 监听窗口resize事件
window.addEventListener('resize', debouncedAdapt);

注意事项

使用防抖时需要注意几个问题:

  • 防抖返回的是一个新的函数,如果需要取消事件绑定,要保存这个返回的函数引用,不能直接用原函数取消
  • 如果防抖函数内部用到了this,需要通过apply或者call绑定正确的上下文,避免this指向错误
  • delay时间需要根据实际场景调整,太短起不到优化效果,太长会影响用户体验

JavaScript防抖debounce函数节流修改时间:2026-06-05 01:57:10

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。