当前位置: 首页 > news >正文

JavaScript防抖与节流:拯救你的网页卡顿危机!

文章目录

  • 🌪️ JavaScript防抖与节流:拯救你的网页卡顿危机!
    • 引言:当"狂点族"遇上网页性能
      • 没有它们会怎样?
    • 一、防抖(debounce):给"多动症"事件设置冷静期
      • 1.1 什么是防抖?
      • 1.2 实现代码(带详细注释)
        • 模式一:延迟执行(经典防抖)
        • 模式二:立即执行+冷却
        • 两种模式对比表
      • 1.3 适用场景(表格对比)
    • 二、节流(throttle):给事件加上"技能冷却时间"
      • 2.1 什么是节流?
      • 2.2 实现代码
        • 方式1:定时器版(尾部执行)
        • 方式2:时间戳版(头部执行)
        • 两种方式对比表格
      • 2.3 防抖与节流对比(箭头图示)
      • 2.4 适用场景(表格对比)
    • 三、防抖与节流的全方位对比
      • 3.1 相同之处
      • 3.2 核心区别
    • 四、性能优化数据对比
    • 结语:成为性能优化大师

在这里插入图片描述

🌪️ JavaScript防抖与节流:拯救你的网页卡顿危机!

引言:当"狂点族"遇上网页性能

想象一下这个场景:小美正在双十一抢购,疯狂点击"立即购买"按钮;老王在调整浏览器窗口大小时,页面元素不断重新计算;小李在搜索框边输入边触发搜索…如果没有防抖和节流,这些操作会让网页像背着10斤重的书包跑步一样喘不过气来!

电商网站搜索框场景

  • 用户输入"最新智能手机"时:
    • 无优化:触发6次搜索请求(每个字符一次)
    • 防抖:只在停止输入300ms后触发1次
    • 节流:每200ms最多触发1次(可能触发3-4次)

没有它们会怎样?

场景问题后果
连续点击提交按钮多次提交表单重复订单、服务器压力大
窗口频繁调整大小持续触发resize事件页面卡顿、CPU占用高
输入框实时搜索每次输入都请求API请求风暴、性能浪费

一、防抖(debounce):给"多动症"事件设置冷静期

1.1 什么是防抖?

“等你说完我再行动” - 就像电梯关门按钮,无论按多少次,只会在最后一次操作后等待一段时间才执行。

1.2 实现代码(带详细注释)

模式一:延迟执行(经典防抖)
/*** 经典防抖:最后一次触发后等待delay毫秒执行* @param {Function} fn - 目标函数* @param {number} delay - 延迟时间(ms)* @returns {Function} - 防抖处理后的函数
*/
function debounce(fn, delay) {// 用于保存定时器ID的闭包变量let timer;// 返回一个包装后的新函数return function(...args) {// 如果已存在定时器,先清除之前的(避免多次触发)if (timer) clearTimeout(timer);// 设置新的定时器,在延迟时间后执行原函数timer = setTimeout(() => {// 使用apply保持原函数的this指向和参数fn.apply(this, args);// 执行后重置定时器变量(非必须,但有助于垃圾回收)timer = null;}, delay);};
}
模式二:立即执行+冷却
/*** 立即执行版防抖:首次触发立即执行,之后进入冷却期* @param {Function} fn    - 需要防抖的原始函数* @param {number}  wait   - 冷却时间(毫秒)* @returns {Function}     - 经过防抖处理的新函数*/
function debounceImmediate(fn, wait) {// 用于保存定时器 ID 的闭包变量let timer;// 返回一个包装后的新函数return function (...args) {// 如果已经有定时器,先清除(重置冷却期)if (timer) clearTimeout(timer);// 判断是否应该立即执行// 当 timer 为 null/undefined 时(即首次触发或已冷却完毕),shouldCallNow 为 trueconst shouldCallNow = !timer;// 设置新的定时器// 定时器到期后把 timer 置空,表示冷却期结束timer = setTimeout(() => {timer = null;}, wait);// 如果需要立即执行,则立即调用原函数if (shouldCallNow) {fn.apply(this, args);}};
}
两种模式对比表
特性延迟执行模式立即执行模式
首次触发不执行立即执行
后续触发重置计时,最后一次执行冷却期内不执行
执行时机停止触发后delay毫秒首次触发立即执行
适用场景搜索建议、窗口resize按钮防重复点击、表单提交

1.3 适用场景(表格对比)

场景不使用防抖使用防抖后
搜索框输入输入每个字符都触发搜索停止输入500ms后才搜索
窗口resize每次像素变化都计算布局调整结束300ms后计算
按钮提交快速点击导致多次提交只认最后一次点击

二、节流(throttle):给事件加上"技能冷却时间"

2.1 什么是节流?

“再着急也得按节奏来” - 就像游戏中的技能CD,无论你按多快,技能都会按照固定频率释放。

2.2 实现代码

方式1:定时器版(尾部执行)
/*** 定时器版节流(保证周期末尾执行)* @param {Function} fn - 需要节流的函数* @param {number} wait - 执行间隔(ms)* @returns {Function} - 节流处理后的函数*/
function throttleByTimer(fn, wait) {let timer = null;return function(...args) {const context = this;if (!timer) {timer = setTimeout(() => {fn.apply(context, args);timer = null;}, wait);}};
}

特点

  • 第一次触发后会等待wait毫秒才执行
  • 保证每个周期末尾会执行一次
  • 停止触发后可能还会执行最后一次

执行流程

事件触发: |--x--x---x----x------x---|
执行时机: |----x----x----x----x-----|(固定间隔末尾执行)
方式2:时间戳版(头部执行)
/*** 时间戳版节流(保证周期开始执行)* @param {Function} fn - 需要节流的函数* @param {number} wait - 执行间隔(ms)* @returns {Function} - 节流处理后的函数*/
function throttleByTimestamp(fn, wait) {let prev = 0; // 上次执行时间戳return function(...args) {const now = Date.now();if (now - prev >= wait) {fn.apply(this, args);prev = now;}};
}

特点

  • 第一次触发立即执行
  • 保证每个周期开始时执行
  • 停止触发后不会再有额外执行

执行流程

事件触发: |--x--x---x----x------x---|
执行时机: |x----x----x----x---------|(固定间隔开始执行)
两种方式对比表格
特性定时器版时间戳版
首次触发延迟执行立即执行
执行时机周期末尾周期开始
停止触发可能执行最后一次不会执行最后一次
实现方式使用setTimeout使用Date.now()
内存占用需要维护timer变量只需维护prev时间戳
适用场景需要平滑结束的操作需要快速响应的操作

2.3 防抖与节流对比(箭头图示)

高频事件触发场景:快速连续触发事件↓
防抖:└──────等待期──────┤执行最后一次↑ 期间触发会重置等待期节流:├─执行─┼──间隔──┼─执行─┤固定时间间隔必执行

2.4 适用场景(表格对比)

场景推荐技术原因
搜索建议防抖用户输入完毕才响应
无限滚动节流定期检查滚动位置
拖拽元素节流保持流畅的UI更新
窗口resize防抖/节流防抖(最终布局)/节流(流畅调整)

三、防抖与节流的全方位对比

3.1 相同之处

共同点说明
控制执行频率两者都能减少高频事件的触发次数
提升性能有效降低CPU使用率、减少不必要的函数调用
闭包应用都利用闭包保存状态(timer/lastTime)
返回新函数都是高阶函数,返回包装后的函数

3.2 核心区别

特性防抖(debounce)节流(throttle)
执行时机最后一次触发后延迟执行固定间隔执行
重置机制新触发会重置计时新触发不影响既定节奏
保证执行快速连续触发时可能永不执行必定会按节奏执行
内存占用需要维护单个timer需要维护timer+lastTime
适用场景关注最终状态(如搜索)关注过程状态(如滚动)

四、性能优化数据对比

通过Chrome DevTools测试相同场景:

操作原生事件防抖处理节流处理
输入100个字符100次调用1次调用20次调用(每5字符)
持续滚动10秒500+次调用1次调用10次调用(每秒1次)
CPU占用峰值85%15%30%

结语:成为性能优化大师

防抖和节流就像前端开发中的"呼吸法":

  • 防抖是深呼气后的暂停(等待稳定)
  • 节流是均匀的腹式呼吸(保持节奏)

记住这个开发者口诀:

“高频事件要优化,防抖节流来帮忙;
输入搜索用防抖,滚动动画节流上;
参数调优看场景,组合使用更健康!”

现在,打开你的开发者工具,找到那些"气喘吁吁"的事件处理器,用合适的策略给它们装上"呼吸调节器"吧! 🚀

http://www.dtcms.com/a/324299.html

相关文章:

  • GitHub 趋势日报 (2025年08月09日)
  • 通过Certbot自动申请更新HTTPS网站的SSL证书
  • vue中使用h5plus
  • 一些js数组去重的实现算法
  • 黑马SpringBoot+Elasticsearch作业2实战:商品搜索与竞价排名功能实现
  • 使用正则表达式检测Base64字符串并提取图片类型及正文的JavaScript函数,代码精简且高效
  • 250810-OpenWebUI集成Dify应用
  • 《设计模式》策略模式
  • STM32的计数模式和pwm模式
  • 亚麻云之数据安家——RDS数据库服务入门
  • sqli-labs-master/Less-62~Less-65
  • 01.【面试题】在SpringBoot中如何实现多数据源配置
  • (Python)爬虫进阶(Python爬虫教程)(CSS选择器)
  • 2025年全国青少年信息素养大赛Scratch编程践挑战赛-小低组-初赛-模拟题
  • Linux系统编程Day11 -- 进程状态的优先级和特性
  • 移动端音频处理实践:59MB变声应用的技术实现分析
  • 机器学习-增加样本、精确率与召回率
  • LeetCode 869.重新排序得到 2 的幂:哈希表+排序(一次初始化)
  • Android 16 KB页面大小适配的权威技术方案总结
  • Android快速视频解码抽帧FFmpegMediaMetadataRetriever,Kotlin(2)
  • Android 开发问题:Invalid id; ID definitions must be of the form @+id/ name
  • 010601抓包工具及证书安装-基础入门-网络安全
  • 浅谈 A2A SDK 核心组件
  • 电脑本地摄像头做成rtsp流调用测试windows系统中
  • 【Docker实战】将Django应用容器化的完整指南
  • Pytorch深度学习框架实战教程-番外篇10-PyTorch中的nn.Linear详解
  • Linux-静态配置ip地址
  • 怎么将视频转换成字幕python作为工具
  • 计算机视觉(CV)——pytorch张量基本使用
  • 深入解析Java中的String、StringBuilder与StringBuffer:特性、区别与最佳实践