JavaScript 中的防抖和节流,它们的区别是什么,以及如何实现?

embedded/2025/2/14 1:53:53/

前端开发中,防抖(Debounce)节流(Throttle)是两种常用的优化高频率事件处理的技术。

它们能够有效减少事件处理函数的执行次数,从而提升页面性能和用户体验。

下面将详细解释这两种技术的概念、区别、实现方法以及在日常开发中的使用建议和注意事项。

一、防抖(Debounce)

概念:防抖是指在事件被触发后,等待一定的时间,如果在这段时间内没有再次触发该事件,则执行一次事件处理函数;如果在等待期间内事件再次被触发,则重新计时。

应用场景

  • 窗口调整大小(resize):用户调整窗口大小时,频繁触发resize事件,使用防抖可以只在用户停止调整后执行一次处理逻辑。
  • 输入框实时搜索:用户在输入框中输入内容时,频繁触发输入事件,使用防抖可以只在用户停止输入一段时间后才发送搜索请求。

实现

/*** 防抖函数* @param {Function} func - 需要防抖处理的函数* @param {number} wait - 等待时间(毫秒)* @param {boolean} immediate - 是否立即执行* @returns {Function} - 返回防抖处理后的函数*/
function debounce(func, wait, immediate = false) {let timeout; // 定义一个定时器变量return function(...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); // 如果需要立即执行,则执行函数};
}// 使用示例
const handleResize = debounce(() => {console.log('窗口大小调整完成');
}, 300);window.addEventListener('resize', handleResize);

代码说明

  • debounce 函数接收一个函数 func、等待时间 wait 和一个布尔值 immediate
  • 返回一个新的函数,在该函数被调用时,会设置一个定时器 timeout,在 wait 时间后执行 func
  • 如果在 wait 时间内再次调用该函数,会清除之前的定时器并重新设置,从而实现防抖效果。
  • 参数 immediate 控制是否在第一次触发时立即执行函数。
二、节流(Throttle)

概念:节流是指在一定的时间间隔内,只执行一次事件处理函数。无论事件触发频率多高,处理函数都会按照固定的时间间隔执行。

应用场景

  • 滚动事件(scroll):用户滚动页面时,频繁触发scroll事件,使用节流可以限制处理函数的执行频率,提升性能。
  • 鼠标移动事件(mousemove):在拖拽操作中,频繁触发mousemove事件,使用节流可以减少处理次数。

实现

/*** 节流函数* @param {Function} func - 需要节流处理的函数* @param {number} wait - 时间间隔(毫秒)* @param {Object} options - 可选参数* @param {boolean} options.leading - 是否在开始时执行* @param {boolean} options.trailing - 是否在结束时执行* @returns {Function} - 返回节流处理后的函数*/
function throttle(func, wait, options = {}) {let timeout = null; // 定时器变量let lastArgs = null; // 上一次的参数let lastThis = null; // 上一次的上下文let lastCallTime = 0; // 上一次调用的时间const later = () => {lastCallTime = options.leading === false ? 0 : Date.now();timeout = null;func.apply(lastThis, lastArgs);if (!timeout) lastArgs = lastThis = null;};return function(...args) {const now = Date.now();if (!lastCallTime && options.leading === false) lastCallTime = now;const remaining = wait - (now - lastCallTime);lastArgs = args;lastThis = this;if (remaining <= 0 || remaining > wait) {if (timeout) {clearTimeout(timeout);timeout = null;}lastCallTime = now;func.apply(lastThis, lastArgs);} else if (!timeout && options.trailing !== false) {timeout = setTimeout(later, remaining);}};
}// 使用示例
const handleScroll = throttle(() => {console.log('页面滚动');
}, 200);window.addEventListener('scroll', handleScroll);

代码说明

  • throttle 函数接收一个函数 func、时间间隔 wait 和一个可选参数对象 options
  • 返回一个新的函数,在该函数被调用时,会根据时间间隔 wait 来决定是否执行 func
  • 参数 options.leading 控制是否在开始时立即执行,options.trailing 控制是否在结束时执行。
  • 通过记录上一次调用的时间和设置定时器,实现节流效果。
三、防抖与节流的区别
特性防抖(Debounce)节流(Throttle)
执行时机在事件停止触发后的一段时间内执行一次在固定的时间间隔内执行一次
适用场景输入框实时搜索、窗口调整大小等需要等待用户停止操作的场景滚动事件、鼠标移动事件等需要限制执行频率的场景
实现方式通过不断重置定时器,确保只有在最后一次触发后的一段时间内没有新的触发才执行通过记录上次执行时间,控制函数的执行频率
四、日常开发中的使用建议
  1. 合理选择防抖和节流

    • 对于需要等待用户停止操作的事件(如输入、窗口调整),使用防抖更为合适。
    • 对于需要限制执行频率的事件(如滚动、拖拽),使用节流更为合适。
  2. 优化用户体验

    • 在高频率触发的事件中,合理使用防抖和节流,可以避免因频繁执行导致的页面卡顿或性能问题。
    • 例如,在搜索框中输入内容时,使用防抖可以减少不必要的搜索请求,提高响应速度。
  3. 结合实际需求调整参数

    • 根据具体业务场景,调整防抖和节流的等待时间或时间间隔,以达到最佳效果。
    • 例如,对于快速滚动的页面,可以将节流的时间间隔设置为100ms,以平衡性能和响应速度。
五、实际开发过程中需要注意的点
  1. 内存管理

    • 确保在组件销毁或不再需要监听事件时,移除相应的事件监听器,防止内存泄漏。
    • 例如,使用 removeEventListener 移除绑定的防抖或节流函数。
  2. 函数上下文和参数传递

    • 在实现防抖和节流时,注意保持原函数的上下文 (this) 和参数,确保函数执行时的正确性。
    • 例如,使用 func.apply(this, args) 来调用原函数。
  3. 兼容性和性能

    • 在不同浏览器和设备上测试防抖和节流的效果,确保兼容性。
    • 避免在节流或防抖函数中执行过于复杂的逻辑,以免影响性能。
  4. 组合使用

    • 在某些复杂场景下,可能需要同时使用防抖和节流,根据具体需求灵活组合使用。

示例:在一个需要同时限制滚动事件频率和搜索输入延迟的场景中,可以分别对滚动事件使用节流,对搜索输入使用防抖。

// 节流处理滚动事件
const handleScrollThrottled = throttle(() => {console.log('滚动事件节流处理');
}, 200);window.addEventListener('scroll', handleScrollThrottled);// 防抖处理搜索输入
const handleSearchDebounced = debounce((query) => {console.log(`搜索内容: ${query}`);
}, 300);searchInput.addEventListener('input', (e) => {handleSearchDebounced(e.target.value);
});

通过合理地组合使用防抖和节流,可以在不同的事件场景中达到最佳的性能优化效果。

防抖和节流是前端开发中优化高频率事件处理的重要技术。

理解它们的概念、区别及实现方法,并在实际开发中合理应用,可以显著提升页面性能和用户体验。

在实际应用中,需根据具体场景选择合适的优化策略,并注意内存管理、函数上下文和参数传递等问题,以确保代码的健壮性和可维护性。


http://www.ppmy.cn/embedded/162018.html

相关文章

DeepSeek-R1-技术文档

模型介绍: DeepSeek - R1 - Zero:通过大规模强化学习训练,不依赖监督微调作为前期步骤,展现出卓越的推理能力,在强化学习过程中自然产生了许多强大且有趣的推理行为。但它存在一些缺陷,比如生成内容可读性欠佳,出现语言混杂的情况。 DeepSeek - R1:为解决DeepSeek - R1…

SpringCloud面试题----如何保证 Spring Cloud 微服务的安全性

网络安全 1. 使用防火墙 边界防火墙:在微服务架构的边界部署防火墙,如硬件防火墙(如 Cisco ASA、Juniper SRX)或软件防火墙(如 Linux 系统的 iptables),根据 IP 地址、端口号和协议等规则限制外部对内部微服务的访问,只允许必要的流量进入。内部防火墙:在微服务之间的…

uniapp开发h5部署到服务器

1.发行>网站-PC Web或手机H5&#xff08;仅适用于uniapp&#xff09; 2.填写网站域名 3.编译成功后会生成一个unpackage文件夹找到下面的h5 4.接下来会使用一个工具把h5里面的文件放到服务器上面&#xff08;WinSCP使用其他能部署的工具也行&#xff09; 5.登录 6.登录成功后…

51单片机俄罗斯方块开机动画

/************************************************************************************************************** * 名称&#xff1a;Game_Star * 功能&#xff1a;开机动画 * 参数&#xff1a;NULL * 返回&#xff1a;NULL ******************************************…

Android新版高斯模糊(毛玻璃)官方实现,Kotlin

Android新版高斯模糊(毛玻璃)官方实现&#xff0c;Kotlin 从Android 12开始&#xff0c;Android官方API支持高斯模糊(毛玻璃)效果。关键是通过RenderEffect实现。 https://developer.android.com/reference/android/graphics/RenderEffecthttps://developer.android.com/refer…

解决VsCode的 Vetur 插件has no default export Vetur问题

文章目录 前言1.问题2. 原因3. 解决其他 前言 提示&#xff1a; 1.问题 Cannot find module ‘ant-design-vue’. Did you mean to set the ‘moduleResolution’ option to ‘node’, or to add aliases to the ‘paths’ option? Module ‘“/xxx/xxx/xxx/xxx/xxx/src/vie…

Serverless 架构与 AWS Lambda 的应用实践

引言 随着云计算的普及&#xff0c;传统的服务器管理方式逐渐被更加灵活和高效的技术所取代&#xff0c;Serverless&#xff08;无服务器&#xff09;架构便是其中一个备受瞩目的创新。在 Serverless 架构下&#xff0c;开发者不再需要关注服务器的部署、维护和扩展问题&#…

设计模式-模版方法

一、定义 模版方法模式在一个方法中定义一个算法的骨架&#xff0c;而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下&#xff0c;重新定义算法中的某些步骤。 模版方法模式是很常见且很有用的一种模式&#xff0c;理解起来也容易。其优点就是保护了…