JavaScript 中的防抖和节流,它们的区别是什么,以及如何实现?
在前端开发中,防抖(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) |
|---|---|---|
| 执行时机 | 在事件停止触发后的一段时间内执行一次 | 在固定的时间间隔内执行一次 |
| 适用场景 | 输入框实时搜索、窗口调整大小等需要等待用户停止操作的场景 | 滚动事件、鼠标移动事件等需要限制执行频率的场景 |
| 实现方式 | 通过不断重置定时器,确保只有在最后一次触发后的一段时间内没有新的触发才执行 | 通过记录上次执行时间,控制函数的执行频率 |
四、日常开发中的使用建议
-
合理选择防抖和节流:
- 对于需要等待用户停止操作的事件(如输入、窗口调整),使用防抖更为合适。
- 对于需要限制执行频率的事件(如滚动、拖拽),使用节流更为合适。
-
优化用户体验:
- 在高频率触发的事件中,合理使用防抖和节流,可以避免因频繁执行导致的页面卡顿或性能问题。
- 例如,在搜索框中输入内容时,使用防抖可以减少不必要的搜索请求,提高响应速度。
-
结合实际需求调整参数:
- 根据具体业务场景,调整防抖和节流的等待时间或时间间隔,以达到最佳效果。
- 例如,对于快速滚动的页面,可以将节流的时间间隔设置为100ms,以平衡性能和响应速度。
五、实际开发过程中需要注意的点
-
内存管理:
- 确保在组件销毁或不再需要监听事件时,移除相应的事件监听器,防止内存泄漏。
- 例如,使用
removeEventListener移除绑定的防抖或节流函数。
-
函数上下文和参数传递:
- 在实现防抖和节流时,注意保持原函数的上下文 (
this) 和参数,确保函数执行时的正确性。 - 例如,使用
func.apply(this, args)来调用原函数。
- 在实现防抖和节流时,注意保持原函数的上下文 (
-
兼容性和性能:
- 在不同浏览器和设备上测试防抖和节流的效果,确保兼容性。
- 避免在节流或防抖函数中执行过于复杂的逻辑,以免影响性能。
-
组合使用:
- 在某些复杂场景下,可能需要同时使用防抖和节流,根据具体需求灵活组合使用。
示例:在一个需要同时限制滚动事件频率和搜索输入延迟的场景中,可以分别对滚动事件使用节流,对搜索输入使用防抖。
// 节流处理滚动事件
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);
});
通过合理地组合使用防抖和节流,可以在不同的事件场景中达到最佳的性能优化效果。
防抖和节流是前端开发中优化高频率事件处理的重要技术。
理解它们的概念、区别及实现方法,并在实际开发中合理应用,可以显著提升页面性能和用户体验。
在实际应用中,需根据具体场景选择合适的优化策略,并注意内存管理、函数上下文和参数传递等问题,以确保代码的健壮性和可维护性。
相关文章:
JavaScript 中的防抖和节流,它们的区别是什么,以及如何实现?
在前端开发中,防抖(Debounce)和节流(Throttle)是两种常用的优化高频率事件处理的技术。 它们能够有效减少事件处理函数的执行次数,从而提升页面性能和用户体验。 下面将详细解释这两种技术的概念、区别、…...
【Kubernetes的SpringCloud最佳实践】Spring Cloud netflix 能否被K8s资源完全替代?
在部署Spring Cloud微服务到Kubernetes(K8s)时, Spring Cloud netflix 是否需要完全替代?或者可以部分替代,结合使用? 例如,服务发现和负载均衡可以交给K8s处理, 但某些功能如API网关…...
MATLAB中extract 函数用法
目录 语法 说明 示例 从地址中提取邮政编码 提取在数值位置处的字符 extract函数的功能是从字符串中提取子字符串。 语法 newStr extract(str,pat) newStr extract(str,pos) 说明 newStr extract(str,pat) 返回 str 中与 pat 指定的模式匹配的任何子字符串。 如果 s…...
DeepSeek-V3:开源多模态大模型的突破与未来
目录 引言 一、DeepSeek-V3 的概述 1.1 什么是 DeepSeek-V3? 1.2 DeepSeek-V3 的定位 二、DeepSeek-V3 的核心特性 2.1 多模态能力 2.2 开源与可扩展性 2.3 高性能与高效训练 2.4 多语言支持 2.5 安全与伦理 三、DeepSeek-V3 的技术架构 3.1 模型架构 3…...
C语言学习笔记:子函数的调用实现各个位的累加和
在C语言程序学习之初,我们都会学习如何打印 hello world,在学习时我们知道了int main()是主函数,程序从main函数开始执行,这是流程控制的一部分内容。在主函数中我们想要实现一些功能,比如求各个…...
docker安装ollama显示超时或失败
正常安装 1、拉取ollma镜像 docker pull ollama/ollama or docker pull docker.1panel.live/ollama/ollama2、运行ollma镜像 docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama3、运行指定大模型:模型仓库参考网站: library (ollama.com…...
grafana面板配置opentsdb
新增面板: 这里add-panel: 如果不是想新增面板而是想新增一行条目,则点击convert to row: 在新增的面板这里可以看到选择数据源 Aggregator:聚合条件,区分下第一行和第二行的aggregator,第一个是对指标值的聚合&…...
iOS AES/CBC/CTR加解密以及AES-CMAC
感觉iOS自带的CryptoKit不好用,有个第三方库CryptoSwift还不错,好巧不巧,清理过Xcode缓存后死活下载不下来,当然也可以自己编译个Framework,但是偏偏不想用第三方库了,于是研究了一下,自带的Com…...
使用Jenkins实现鸿蒙HAR应用的自动化构建打包
使用Jenkins实现鸿蒙HAR应用的自动化构建打包 在软件开发领域,自动化构建是提高开发效率和确保代码质量的重要手段。特别是在鸿蒙(OpenHarmony)应用开发中,自动化构建更是不可或缺。本文将详细介绍如何使用Jenkins命令行工具实现…...
2025年02月10日Github流行趋势
项目名称:dify 项目地址url:https://github.com/langgenius/dify项目语言:TypeScript历史star数:64707今日star数:376项目维护者:takatost, crazywoola, laipz8200, iamjoel, JohnJyong项目简介:…...
Ansible简单介绍及用法
一、简介 Ansible是一个简单的自动化运维管理工具,基于Python语言实现,由Paramiko和PyYAML两个关键模块构建,可用于自动化部署应用、配置、编排task(持续交付、无宕机更新等)。主版本大概每2个月发布一次。 Ansible与Saltstack最大的区别是…...
渗透利器工具:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)
Burp Suite 联动 XRAY 图形化工具.(主动扫描被动扫描) Burp Suite 和 Xray 联合使用,能够将 Burp 的强大流量拦截与修改功能,与 Xray 的高效漏洞检测能力相结合,实现更全面、高效的网络安全测试,同时提升漏…...
HTML-day1(学习自用)
目录 一、HTML介绍 二、常用的标签 1、各级标题(h1-h6) 2、段落标签(p) 3、文本容器(span) 4、图片标签(img) 5、超链接标签(a) 6、表格(t…...
Vue07
一、Vuex 概述 目标:明确Vuex是什么,应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具,状态就是数据。 大白话:Vuex 是一个插件,可以管理 Vue 通用的数据 (多组件共享的数据)。例如:购物车数…...
Godot开发框架探索#2
前言 距离上次发文又又又隔了很长一段时间。主要原因还是因为思绪在徘徊,最近纠结的点有以下几个:1.渴求一个稳定的Godot开发框架;2.要不要使用更轻量的开发框架,或者直接写引擎; 3.对自己想做的游戏品类拿不定主意。…...
deepseek实现私有知识库
前言 之前写了如何本地部署deepseek,已经可以私有化问答了,本地搭建deepseek实操(ollama搭建,docker管理,open-webui使用) 其中我觉得最厉害的还是这个模型蒸馏,使我们可以用很低的代价使用大模…...
2.10学习总结
Dijkstra算法求取最短路径 注:迪杰斯特拉算法并不能直接生成最短路径,但是算法将最短路径信息保存在dist数组和path数组中。 dist数组中保存的是起始点到数组下标对应顶点的路径长度(累加的结果)path数组中保存的是对应path数组…...
【探索未来科技】2025年国际学术会议前瞻
【探索未来科技】2025年国际学术会议前瞻 【探索未来科技】2025年国际学术会议前瞻 文章目录 【探索未来科技】2025年国际学术会议前瞻前言1. 第四届电子信息工程、大数据与计算机技术国际学术会议( EIBDCT 2025)代码示例:机器学习中的线性回…...
pytest.fixture
pytest.fixture 是 pytest 测试框架中的一个非常强大的功能,它允许你在测试函数运行前后执行一些设置或清理代码。以下是关于 pytest.fixture 的详细介绍: 一、定义与用途 pytest.fixture 是一个装饰器,用于标记一个函数为 fixture。Fixture 函数中的代码可以在测试函数运…...
大模型基本原理(四)——如何武装ChatGPT
传统的LLM存在几个短板:编造事实、计算不准确、数据过时等,为了应对这几个问题,可以借助一些外部工具或数据把AI武装起来。 实现这一思路的框架包括RAG、PAL、ReAct。 1、RAG(检索增强生成) LLM生成的内容会受到训练…...
开发完的小程序如何分包
好几次了,终于想起来写个笔记记一下 我最开始并不会给小程序分包,然后我就各种搜,发现讲的基本上都是开发之前的小程序分包,可是我都开发完要发布了,提示我说主包太大需要分包,所以我就不会了。。。 好了…...
java配置api,vue网页调用api从oracle数据库读取数据
一、主入口文件 1:java后端端口号 2:数据库类型 和 数据库所在服务器ip地址 3:服务器用户名和密码 二、映射数据库表中的数据 resources/mapper/.xml文件 1:column后变量名是数据库中存储的变量名 property的值是column值的…...
iOS三方登录 - Facebook登录
引言 在出海APP的开发中,集成主流社交平台的三方登录已成为必不可少的一环。Facebook 作为全球最大的社交网络平台之一,其提供的 Facebook 登录功能能够大大简化用户注册和登录流程,提高用户体验,减少流失率。对于开发者而言&…...
使用 OpenGL ES 渲染一个四边形
使用 OpenGL ES 渲染一个四边形 在 iOS 开发中,OpenGL ES 是一个强大的工具,用于实现高性能的 2D 和 3D 图形渲染。本文将通过一个完整的代码示例,详细解析如何使用 OpenGL ES 渲染一个简单的四边形。我们将从基础概念入手,逐步讲解代码的每个部分,帮助你理解 OpenGL ES …...
机器学习 - 理解偏差-方差分解
为了避免过拟合,我们经常会在模型的拟合能力和复杂度之间进行权衡。拟合能力强的模型一般复杂度会比较高,容易导致过拟合。相反,如果限制模型的复杂度,降低其拟合能力,又可能会导致欠拟合。因此,如何在模型…...
深入解析 Android 系统属性 跨进程 API:SystemProperties、ContentObserver 的使用
基础篇.系统属性 & 跨进程 API 📢 1. 职业规划篇 来聊聊安卓职业规划?整机开发大专能做么? 📢 2.基础篇 基础篇.前言 基础篇.编译环境搭建 基础篇.源码目录简介 基础篇.系统 mk_bp 讲解 基础篇.开机动画定制 基础篇.定制桌面壁…...
从 .NET Framework 升级到 .NET 8 后 SignalR 问题处理与解决方案
随着 .NET Framework 向 .NET 8 的迁移,许多开发者在使用 SignalR 时遇到了一些前后端连接、配置、调用等方面的问题。尤其是在处理 SignalR 实时通信功能时,升级后的一些兼容性问题可能导致应用程序无法正常工作。本文将介绍在从 .NET Framework 升级到…...
深入解析 Linux 系统中 Cron 定时任务的配置与管理
在 Linux 和类 Unix 系统中,cron 是一个非常强大的工具,用于定时执行各种任务,例如自动备份、定时运行脚本和定期清理日志文件。通过合理配置 cron,你可以让很多系统维护任务自动化,从而减轻日常管理的压力。而 cronta…...
深度学习01 神经网络
目录 神经网络 感知器 感知器的定义 感知器的数学表达 感知器的局限性 多层感知器(MLP, Multi-Layer Perceptron) 多层感知器的定义 多层感知器的结构 多层感知器的优势 偏置 偏置的作用 偏置的数学表达 神经网络的构造 神经网络的基本…...
ffmpeg基本用法
一、用法 ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... 说明: global options:全局选项,应用于整个 FFmpeg 进程,它们通常不受输入或输出部分的限制。 infile options:输入选…...
