JavaScript:节流与防抖

目录

一、前言

二、节流(Throttle)

1、定义

2、使用场景

3、实现原理

4、代码示例

5、封装节流函数 

三、防抖(Debounce)

1、定义

2、使用场景

3、实现原理

4、代码示例

5、封装防抖函数 

四、异同点总结


一、前言

在JavaScript中,通常需要用到一些事件,比如:按钮的click事件、输入框的keydown事件、鼠标的mousemove事件、浏览器的resize事件等。

这些事件都可能被高频触发,会不断的执行回调函数,从而导致一些资源浪费,影响前端性能;

如何优化呢?

JavaScript中的节流(Throttle)与防抖(Debounce)是两种优化高频执行函数的方法;

主要用于控制函数执行的频率,从而减少不必要的资源消耗,提高页面性能;

二、节流(Throttle)

1、定义

节流是指,当事件被连续触发时,在设定的一段时间内,只执行一次该事件的回调函数

也就是说,执行一次事件的回调函数后,等到间隔时间结束,若再触发该事件,才会再执行该事件的回调函数;

将高频执行变成每隔一段时间执行

举个例子

  • 假设一个事件的间隔时间是3秒,当第一次触发了该事件,会执行该事件的回调函数,
  • 3秒间隔内,再触发该事件,并不会再执行该事件的回调函数;
  • 直到3秒钟过后,再触发该事件,才会再执行该事件的回调函数;

2、使用场景

(1)多次点击按钮

当一个搜索按钮被连续多次点击时,并不是每次点击都发送请求,会存在一个间隔时间,距上次点击完获取数据后,间隔几秒钟,再点击才会重新请求加载数据;

(2)频繁下拉刷新

同样的,当页面被频繁下拉刷新时,并不是每次下拉都发送请求重新加载数据,会存在一个间隔时间,距上次刷新完几秒钟后,再下拉才会重新请求加载数据;

3、实现原理

利用定时器setTimeout设置间隔时间;

  • 每次执行事件的回调函数,都会添加一个新的定时器,到了设定时间再清除这个定时器;
  • 通过判断定时器是否存在,即可得到设置的计时是否结束;
  • 若定时器存在(未被清除),说明计时还未结束,本次不执行事件的回调函数;
  • 若定时器不存在(已被清除),说明计时已经结束,本次要执行事件的回调函数;

4、代码示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>节流与防抖</title>
</head><body><button class="zyl-button">点击按钮</button>
</body>
<script>// 获取button按钮var zyl_button = document.querySelector(".zyl-button");// 使用节流let timerId_1 = null;zyl_button.addEventListener("click", function () {if (!timerId_1) {console.log("使用节流,每间隔3秒,再点击按钮才会被执行!");timerId_1 = setTimeout(() => {timerId_1 = null;}, 3000);}})
</script></html>

  • 按钮第一次被点击,执行打印输出;
  • 接着连续点击不会打印输出;
  • 直到距离上一次3秒钟过后,再点击才会继续打印输出; 

5、封装节流函数 

对节流函数进行封装,可以在需要的地方直接调用;

// 节流函数
function throttle(fn, time) {let timerId_1 = null;return function (...args) {if (!timerId_1) {fn.apply(this, args);timerId_1 = setTimeout(() => {timerId_1 = null}, time);}};
}

在上述示例中使用封装的节流函数 :

<script>// 获取button按钮var zyl_button = document.querySelector(".zyl-button");// 点击按钮的回调函数function handleClick() {console.log(this);console.log("使用节流,每间隔3秒,再点击按钮才会被执行!");}// 点击按钮 使用节流函数zyl_button.addEventListener('click', throttle(handleClick, 3000));// 节流函数function throttle(fn, time) {let timerId_1 = null;return function (...args) {if (!timerId_1) {fn.apply(this, args);timerId_1 = setTimeout(() => {timerId_1 = null}, time);}};}
</script>

三、防抖(Debounce)

1、定义

防抖:当事件被连续触发时,只有在最后一次触发事件后的延迟时间内没有再次触发,才会执行目标函数;

也就是说,事件被触发后,不会立即执行该事件的回调函数,若在该事件的延迟时间内,没有再触发该事件,则执行该事件的回调函数

将高频执行变成在最后一次执行

举个例子

  • 假设一个事件的延迟时间是3秒,当触发了该事件,则它的回调函数会在3秒后执行;
  • 在这延迟的3秒期间,如果又触发了该事件,则会重新开始计时3秒钟
  • 如果又触发,就再重新计时,再触发,再重新计时......;
  • 直到距离事件的触发时间(延迟时间),大于3秒钟,才会执行该事件的回调函数;

2、使用场景

(1)搜索框的输入搜索

每次输入内容都去请求数据,请求次数过多,非常浪费资源;可以设置一个输入延迟时间(1秒),输入内容1秒钟后,再去发送请求,获取搜索结果;通过减少请求次数,提升性能;

(2)文本编辑器的实时保存

没必要每次编辑内容都进行保存,同样可以设置一个延迟时间(3秒),编辑内容3秒钟后,再自动发送请求,保存数据;

3、实现原理

利用定时器setTimeout设置延迟时间;

  • 每次事件触发时,先判断是否有延时定时器;
  • 有则清除,没有则创建一个新的延时定时器;
  • 在延时定时结束后,才会执行回调函数;
  • 若延时时间未结束前(定时器存在),再次触发该事件,清除旧的定时器,并设置新的定时器,重新开始计时;

4、代码示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>节流与防抖</title>
</head><body><input class="zyl-input" type="text"><br><br>
</body>
<script>// 获取input框var zyl_input = document.querySelector(".zyl-input");// 使用防抖let timerId_2 = nullzyl_input.addEventListener("keydown", function () {if (timerId_2) {clearTimeout(timerId_2);}timerId_2 = setTimeout(() => {console.log("使用防抖,3秒延迟内,没有再次触发该事件,则该回调函数被执行!");}, 3000);})
</script></html>

  • 在文本框中输入内容,打印输出并不会立即执行;
  • 只有在输入停止3秒钟后才会打印输出;

5、封装防抖函数 

对防抖函数进行封装,可以在需要的地方直接调用;

// 防抖函数
function debounce(fn, time) {let timerId_2;return function (...args) {if (timerId_2) {clearTimeout(timerId_2);}timerId_2 = setTimeout(() => {fn.apply(this, args);}, time);};
}

在上述实例中使用防抖函数 :

<script>// 获取input框var zyl_input = document.querySelector(".zyl-input");// 输入内容的回调函数function handleInput() {console.log(this);console.log("使用防抖,3秒延迟内,没有再次触发该事件,则该回调函数被执行!");}// 输入内容 使用防抖函数zyl_input.addEventListener('keydown', debounce(handleInput, 3000));// 防抖函数function debounce(fn, time) {let timerId_2;return function (...args) {if (timerId_2) {clearTimeout(timerId_2);}timerId_2 = setTimeout(() => {fn.apply(this, args);}, time);};}
</script>

四、异同点总结

异同点节流防抖
相同点1.函数目标都是为了优化事件处理,减少不必要的函数调用;
2.应用场景用于处理频繁触发的事件,以减轻应用的性能负担;
3.实现方式都可以通过setTimeout定时器,设定时间间隔来实现;
不同点1.触发机制节流在设定的时间间隔内只执行一次函数;防抖则是在事件停止触发后执行一次函数;
2.执行时机节流在事件触发时立即执行,但可能在时间间隔的末尾执行一次;防抖则是在事件停止触发后执行一次;
3.适用场景节流适用于需要在一段时间内处理一次事件的场景,如定时刷新页面数据;防抖适用于需要在事件停止触发后执行一次操作的场景,如输入框的值变化;

=========================================================================

每天进步一点点~!

记录一下 节流和防抖 这两个重要的技术~~!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/48556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Adobe Premiere Pro(Pr)安装包软件下载

一、简介 Adobe Premiere Pro&#xff08;简称Pr&#xff09;是由Adobe公司开发的一款功能强大的视频编辑软件。它支持多平台使用&#xff0c;包括Windows和Mac系统&#xff0c;并且拥有良好的兼容性和高效的性能。Premiere Pro不仅提供了视频剪辑、特效添加、音频处理等基本功…

《从C/C++到Java入门指南》- 9.字符和字符串

字符和字符串 字符类型 Java 中一个字符保存一个Unicode字符&#xff0c;所以一个中文和一个英文字母都占用两个字节。 // 计算1 .. 100 public class Hello {public static void main(String[] args) {char a A;char b 中;System.out.println(a);System.out.println(b)…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 二进制游戏(200分)- 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

Transformer之Vision Transformer结构解读

论文地址 代码地址 写在前面 什么是Transformer呢&#xff1f;就是把符号向量化为Token&#xff0c; 再和位置编码求和或者做阿达玛积&#xff0c;最后送入一定层数的Attention Block构成的Encoder和Decoder&#xff0c;就完成了Transformer的基础功能。 那么&#xff0c;把上…

idea2019版本创建JavaWeb项目并配置Tomcat步骤

一、创建JavaWeb项目 1.新建项目File->New->Project 2. 选择JavaWeb应用在New Project窗口中选择Java后勾选Java EE中的Web Application后点击next即可 3.设置项目名称后点击finish即可 4.至此项目创建完成&#xff0c;检查文件是否齐全&#xff0c;开始配置Tomcat 二、…

IDEA工具中Java语言写小工具遇到的问题

一&#xff1a;读取excel时遇到 org/apache/poi/ss/usermodel/WorkbookProvider 解决办法&#xff1a; 在pom.xml中把poi的引文包放在最前面即可&#xff08;目前就算放在最后面也不报错了&#xff0c;不知道为啥&#xff09; 二&#xff1a;本地maven打包时&#xff0c;没有…

base SAS programing学习笔记(read raw files2)

使用COLUMN input和FORMATTED input读入固定位置的外部文件&#xff1b;如下图所示&#xff0c; 1.COLUMN input &#xff08;按列数读入外部文件数据&#xff09; 使用column input 不需要按从左到右的顺序读取外部文件的数值&#xff0c;可以是任意读取&#xff0c;也可以重…

STM32F103定时器中断详解

目录 目录 目录 前言 一.什么是定时器 1.1 STM32F103定时器概述 1.2基本定时器 1.2通用定时器 1.3高级定时器 1.4 三种定时器区别 基本定时器&#xff08;Basic Timer&#xff09; 通用定时器&#xff08;General-Purpose Timer&#xff09; 高级定时器&#xff08;Advanced Ti…

ubuntu2204配置anacondacuda4090nvidia驱动

背景 某个机房的几台机器前段时间通过dnat暴露至公网后被入侵挖矿&#xff0c;为避免一些安全隐患将这几台机器执行重装系统操作&#xff1b; 这里主要记录配置nvidia驱动及cuda&anaconda。 步骤 大概分为几个步骤 禁用nouveau配置grub显示菜单install nvidia-driveri…

基于Python+Django,开发的一个在线教育系统

一、项目简介 使用Python的web框架Django进行开发的一个在线教育系统&#xff01; 二、所需要的环境与组件 Python3.6 Django1.11.7 Pymysql Mysql pure_pagination DjangoUeditor captcha xadmin crispy_forms 三、安装 1. 下载项目后进入项目目录cd Online-educ…

配置RIPv2的认证

目录 一、配置IP地址、默认网关、启用端口 1. 路由器R1 2. 路由器R2 3. 路由器R3 4. Server1 5. Server2 二、搭建RIPv2网络 1. R1配置RIPv2 2. R2配置RIPv2 3. Server1 ping Server2 4. Server2 ping Server1 三、模拟网络攻击&#xff0c;为R3配置RIPv2 四、在R…

Linux:Linux权限

目录 1. Linux权限的概念 2. Linux权限管理 2.1 文件访问者的分类 2.2 文件类型和访问权限 2.2.1 文件类型 2.2.2 基本权限 2.3 文件权限值的表示方法 2.4 文件访问权限的相关设置方法 2.4.1 chmod 2.4.2 chown 2.4.3 chgrp 2.4.4 umask 3. file指令 4. Linux目…

base SAS programming学习笔记13(Array)

1.Array array-name{dimension} <elements> array-name&#xff1a;向量名称 dimension&#xff1a;向量长度&#xff0c;默认为1&#xff1b; elements:列出变量名&#xff0c;变量名要么全是数值变量或者全是字符变量 array-name和variable不能相同&#xff1b;也不能和…

C++面试题之判断一个变量是不是指针

对于变量其实对应的就是内存&#xff0c;而内存并没有表明一定是什么数据类型&#xff0c;所以判断变量是否是一个指针其实是一个参数类型匹配问题&#xff0c;在C中支持函数的重载&#xff0c;那么不同的函数因为参数的不同从而匹配不同函数调用过程。 编译器在进行函数匹配调…

JAVA周总结(集合) 0721day

一.Collection集合 集合:可以存放多种类型数据的容器。 集合和数组的区别 数组的长度是固定的,集合的长度根据存储的数据发生改变。 数组只能存同一种类型的数组,而集合可以存多种类型。 1.2 单列集合常用类的继承体系 java.util.List: 添加的元素是有序、可重复 ; Lis…

PostgreSQL简介和安装

一、Postgresql简介&#xff1a; 1、PostgreSql是功能强大的&#xff0c;开源的关系型数据库&#xff0c;底层基于C语言实现&#xff1b; 2、开源&#xff1a;允许对PostgreSql进行封装&#xff0c;用于商业收费&#xff1b; 3、版本迭代速度快&#xff0c;正式版本已经到15.R…

【轻松拿捏】java中为什么要使用克隆?如何实现对象克隆?深拷贝和浅拷贝区别是什么?

java中为什么要使用克隆&#xff1f;如何实现对象克隆&#xff1f;深拷贝和浅拷贝区别是什么&#xff1f; 一、如何在Java中实现对象克隆 1.1 浅拷贝 1.2 深拷贝 1.3 区别总结 二、面试回答技巧 1. 定义克隆及其用途 2. 解释浅拷贝和深拷贝 3. 具体实现浅拷贝和深拷贝 …

【Python】使用库 -- 详解

库就是别人已经写好了的代码&#xff0c;可以让我们直接拿来用。 一个编程语言能不能流行起来&#xff0c;一方面取决于语法是否简单方便容易学习&#xff0c;一方面取决于生态是否完备。所谓的 “生态” 指的就是语言是否有足够丰富的库&#xff0c;来应对各种各样的场景。在…

LeetCode 188题: 买卖股票的最佳时机IV优化(原创)

之前完成了LeetCode 188题&#xff1a; 买卖股票的最佳时机IV&#xff08;原创&#xff09;-CSDN博客&#xff0c;虽然完成代码编写&#xff0c;并提交成功&#xff0c;但运行效率还未达到最优的1ms&#xff0c;见下图&#xff1a; 仔细检查代码&#xff0c;感觉还是有可优化的…

OpenCV中的GrabCut图像分割算法的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 功能描述 GrabCut 算法是一种用于图像分割的技术&#xff0c;由 Carsten Rother、Vladimir Kolmogorov 和 Andrew Blake 在 2004 年 SIGGRAPH 会议的论文《…