前端学习日记 - 前端函数防抖详解

前端学习日记 - 前端函数防抖详解

前端函数防抖详解

在现代 Web 应用中,函数防抖(debounce)是一种常见且高效的性能优化手段,用于限制高频事件触发下的函数调用次数,从而减少不必要的计算、网络请求或 DOM 操作。本文将从“为什么使用防抖”切入,介绍典型的应用场景,深入解析防抖原理,并给出从零实现到在实际项目中使用 Lodash 的完整代码示例,帮助你快速掌握前端防抖技术。

在这里插入图片描述

为什么使用防抖

函数防抖的核心思想是在连续触发的事件停止后,仅执行最后一次调用,以避免频繁触发带来的性能问题 ([MDN Web Docs][1])。
在不使用防抖的情况下,例如在 input 输入事件或 window.resize 事件中直接调用逻辑,页面可能会因短时间内大量调用而出现卡顿或请求风暴 ([GeeksforGeeks][2])。
通过防抖,可以让函数在用户停止输入、滚动或调整窗口大小后的一定延迟内才执行,极大提高资源利用效率并提升用户体验 ([Medium][3])。

函数防抖的应用场景

  1. 输入框实时搜索建议
    在用户输入关键词时触发搜索接口,若不加限制,每次 keyup 都会发起请求,极易导致接口压力过大。使用防抖后,只在用户停止输入(如 300ms)后才发送请求,有效降低调用次数 ([自由代码营][4])。
  2. 按钮防连点
    对于提交表单或支付按钮,连续点击可能导致多次提交。给点击事件绑定防抖函数,可在用户短时间内多次点击时只执行一次提交操作 ([DEV Community][5])。
  3. 窗口大小调整(resize)
    当页面布局需根据窗口大小实时计算或重绘时,resize 事件会频繁触发,添加防抖能减少重绘次数,提升性能 ([Medium][6])。
  4. 滚动监听
    结合无限滚动或懒加载,当用户滚动页面时应控制数据加载频率,避免重复请求或过度渲染 ([Medium][3])。

函数防抖原理与手写实现

原理

防抖函数通过内部维护一个定时器 ID,每次调用时先清除之前的定时器,再启动一个新的延迟执行定时器;只有在最后一次调用后的延迟时间到达后,才真正执行目标函数 ([GeeksforGeeks][2], [Gist][7])。

手写实现

/** * 简易版防抖函数 * @param {Function} func - 需要防抖的函数 * @param {number} wait - 延迟时间(毫秒) * @returns {Function} - 防抖后返回的新函数 */functiondebounce(func, wait){let timeoutId;// 声明定时器 IDreturnfunction(...args){// 返回一个闭包函数clearTimeout(timeoutId);// 清除上一次定时器 timeoutId =setTimeout(()=>{// 启动新的定时器func.apply(this, args);// 延迟执行目标函数}, wait);};}

上述代码利用 JavaScript 闭包,让每个防抖函数维护独立的 timeoutId,在多次调用时只有最后一次延迟结束后触发 ([Stack Overflow][8])。

使用 Lodash 的 _.debounce

在实际项目中,为了减少手写错误并获得更丰富的功能(如 leadingtrailingcancelflush 等选项),推荐使用成熟的工具库 Lodash 的 _.debounce 方法 ([Lodash][9])。

# 安装 lodash.debounce 子模块npminstall lodash.debounce 
import debounce from'lodash.debounce';/** * 在搜索框中使用防抖 * 当用户停止输入 300ms 后才触发搜索 */const searchInput = document.getElementById('search');functiononSearch(query){// 发送搜索请求 console.log('搜索关键词:', query);}const debouncedSearch =debounce(onSearch,300,{ leading:false, trailing:true}); searchInput.addEventListener('input',(e)=>{debouncedSearch(e.target.value);});
  • leading: 是否在延迟开始前调用一次,默认 false
  • trailing: 是否在延迟结束后调用一次,默认 true
  • 返回的函数还拥有 cancel()flush() 方法,可在需要时取消或立即执行待定调用 ([GeeksforGeeks][10])。

完整示例:防抖搜索组件

下面给出一个完整的示例,包括 HTML、样式与 JavaScript 代码,你可以直接复制运行:

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>Debounce Demo</title><style>body{font-family: sans-serif;padding: 2rem;}#results{margin-top: 1rem;}.item{padding: 0.5rem 0;border-bottom: 1px solid #eee;}</style></head><body><h1>Debounce 搜索示例</h1><inputid="search"type="text"placeholder="输入关键词…"autocomplete="off"/><divid="results"></div><scripttype="module">import debounce from'lodash.debounce';const search = document.getElementById('search');const results = document.getElementById('results');// 模拟异步搜索函数asyncfunctionfetchResults(query){// 假数据return['苹果','香蕉','橘子','西瓜'].filter(item=> item.includes(query));}asyncfunctionhandleSearch(query){const list =awaitfetchResults(query); results.innerHTML = list.map(item=>`<div>${item}</div>`).join('');}// 300ms 防抖,禁止 leading,允许 trailingconst debouncedHandle =debounce(handleSearch,300,{ leading:false}); search.addEventListener('input',e=>{const q = e.target.value.trim();if(q)debouncedHandle(q);else results.innerHTML ='';});</script></body></html>

结语

函数防抖是前端性能优化中的一项基础技术,适用于各种需要限制高频事件调用的场景,通过简单的定时器逻辑或成熟的 Lodash 工具库,就能快速落地。掌握防抖和其“兄弟”节流(throttle),能让你的应用在面对频繁用户交互时依然保持流畅、稳定。欢迎在项目中实践并根据业务需求调整参数,实现更灵活的性能优化。

Read more

山东菏泽测试员:我是如何靠AI逆袭年薪60万的?

山东菏泽测试员:我是如何靠AI逆袭年薪60万的?

一、起点:外包测试员的困境与觉醒 作为一名来自山东菏泽的软件测试员,我最初深陷外包行业的典型困境:价值感低微,被视为“人肉执行器”,只负责重复性手工测试或基础功能验证,难以触及核心业务逻辑。技术成长严重受限,项目周期短且切换频繁,缺乏系统性沉淀机会;职业通道狭窄,晋升至测试开发或管理岗位异常艰难,薪资长期停滞在低位。工作稳定性差,项目结束即面临失业风险,创新参与度几乎为零。2018年,我的年薪不足10万元,菏泽作为三四线城市,资源匮乏加剧了这些挑战。然而,AI技术的崛起——特别是AI-Testing领域的突破——成为转折点。AI不仅能自动化海量重复任务(如用例生成和执行),还能辅助复杂测试(如智能探索性测试),释放人力并提升洞察力。这让我意识到:掌握AI不是取代测试员,而是重塑价值链的关键,是逆袭的起点。 二、逆袭第一步:从工具使用者到效率大师 要突破年薪瓶颈,我首先聚焦效率革命,利用AI将自己从低价值劳动中解放。起步阶段,我自学Python和机器学习基础,通过在线课程(如Coursera)掌握Selenium、Appium等自动化框架。但传统工具局限明显:用例执行依赖静态脚本,

大模型Token入门详解:概念、原理、换算与核心作用【AI基础】

用通俗直白的语言拆解Token相关知识点,全程无晦涩术语,适合AI初学者、大模型入门人群快速掌握核心逻辑,干货好懂易记。 一、Token核心定义:大模型的语言基础单元 我们常说的大语言模型上下文窗口,它的计量单位并不是日常的字数或者词语数,而是Token。大模型的本质是做数字矩阵运算,本身无法直接理解人类的自然语言,必须依靠Tokenizer(分词器)充当“翻译官”,完成文字与数字之间的双向转换,这也是大模型能够理解、生成文字的核心前提。 二、Tokenizer两大核心功能:编码与解码 分词器Tokenizer的工作流程主要分为两步,分工明确且逻辑连贯,支撑起语言与机器指令的转换闭环: * 编码(Encoding):将用户输入的文本内容,转换成模型能够识别的数字序列,包含两个关键步骤。第一步是切分,把完整的语句拆分成模型可处理的最小单元,也就是Token;第二步是映射,为每个Token分配专属的数字编号,即Token ID,让模型能够读取和处理。 * 解码(Decoding):把模型输出的Token ID,反向还原成人类可以正常读懂的自然文字,该过程不需要再次对文本进

一文搞懂MCP、Agent、Skills:AI时代三大核心概念深度对比,搞懂了少走3年弯路

一文搞懂MCP、Agent、Skills:AI时代三大核心概念深度对比,搞懂了少走3年弯路

先搞懂MCP:一个容易混淆的术语 MCP有两个不同的含义 很多人看到"MCP"就懵了,因为这个缩写在AI领域有两个完全不同的含义: 含义1:Model Context Protocol(Anthropic提出的开放协议) 官方定义: MCP是Anthropic在2024年11月发布的开放协议,让AI应用能够标准化地连接数据源和工具。 大白话解释: 就像USB接口统一了设备连接标准一样,MCP统一了AI应用与工具之间的连接方式。 之前的问题: * ChatGPT要接入Google搜索,需要专门写代码 * Claude要接入同样的搜索,又要重新写一遍 * 每个AI应用都要为每个工具写专门的对接代码 有了MCP: * 工具开发者按MCP标准开发一次 * 所有支持MCP的AI应用都可以直接使用 * 就像插USB设备一样简单 这才是当前AI社区讨论最多的"MCP"! ✅ 含义2:Control Plane(AI系统的控制层) 有些文章会把AI系统的控制层也叫"MCP"(Model Control Plane),但这不是标准术语。 更准确的叫法是: * O

【GitHub项目推荐--AutoResearch:AI自主研究代理,让AI自己优化AI模型】⭐⭐⭐⭐⭐

简介 AutoResearch 是由知名AI研究员Andrej Karpathy开发的开源项目,其核心使命是创建一个完全自主的AI研究系统,让AI代理能够自行设计和优化神经网络模型。该项目代表了一种全新的研究范式:不再是人类研究者手动调整超参数和架构,而是将整个研究过程交给AI代理自主进行。AutoResearch提供了一个精简但完整的LLM训练环境,AI代理可以在这个环境中不断实验、评估、迭代,最终发现更优的模型配置。 核心定位:AutoResearch的核心价值在于将AI研究过程本身自动化。传统AI研究依赖于人类研究者的直觉、经验和试错,这个过程既耗时又受限于人类认知的局限性。AutoResearch通过固定时间预算的自主实验循环,实现了研究过程的规模化、系统化和无偏见优化。项目设计哲学是"让AI研究AI",探索在有限计算资源下,自主代理能否超越人类的研究效率。 技术背景:项目基于简化的单GPU nanochat实现,采用Python开发,依赖PyTorch等基础库。整个代码库保持极简设计,只有三个核心文件:prepare.py(数据准备和工具)、train.py(模型和训练