什么是防抖和节流?有什么区别?如何实现?

在这里插入图片描述


文章目录

  • 一、是什么
    • 定义
    • 代码实现
      • 节流
      • 防抖
  • 二、区别
  • 三、应用场景


一、是什么

本质上是优化高频率执行代码的一种手段

如:浏览器的 resizescrollkeypressmousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能

为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率

定义

  • 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
  • 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
    一个经典的比喻:

想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应

假设电梯有两种运行策略 debouncethrottle,超时设定为15秒,不考虑容量限制

电梯第一个人进来后,15秒后准时运送一次,这是节流

电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖

代码实现

节流

完成节流可以使用时间戳与定时器的写法

使用时间戳写法,事件会立即执行,停止触发后没有办法再次执行

function throttled1(fn, delay = 500) {
    let oldtime = Date.now()
    return function (...args) {
        let newtime = Date.now()
        if (newtime - oldtime >= delay) {
            fn.apply(null, args)
            oldtime = Date.now()
        }
    }
}

使用定时器写法,delay毫秒后第一次执行,第二次事件停止触发后依然会再一次执行

function throttled2(fn, delay = 500) {
    let timer = null
    return function (...args) {
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(this, args)
                timer = null
            }, delay);
        }
    }
}

可以将时间戳写法的特性与定时器写法的特性相结合,实现一个更加精确的节流。实现如下

function throttled(fn, delay) {
    let timer = null
    let starttime = Date.now()
    return function () {
        let curTime = Date.now() // 当前时间
        let remaining = delay - (curTime - starttime)  // 从上一次到现在,还剩下多少多余时间
        let context = this
        let args = arguments
        clearTimeout(timer)
        if (remaining <= 0) {
            fn.apply(context, args)
            starttime = Date.now()
        } else {
            timer = setTimeout(fn, remaining);
        }
    }
}

防抖

简单版本的实现

function debounce(func, wait) {
    let timeout;

    return function () {
        let context = this; // 保存this指向
        let args = arguments; // 拿到event对象

        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}

防抖如果需要立即执行,可加入第三个参数用于判断,实现如下:

function debounce(func, wait, immediate) {

    let timeout;

    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout); // timeout 不为null
        if (immediate) {
            let callNow = !timeout; // 第一次会立即执行,以后只有事件执行后才会再次触发
            timeout = setTimeout(function () {
                timeout = null;
            }, wait)
            if (callNow) {
                func.apply(context, args)
            }
        }
        else {
            timeout = setTimeout(function () {
                func.apply(context, args)
            }, wait);
        }
    }
}

二、区别

相同点:

  • 都可以通过使用 setTimeout 实现
  • 目的都是,降低回调执行频率。节省计算资源

不同点:

  • 函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeoutsetTimeout 实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
  • 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
    例如,都设置时间频率为500ms,在2s时间内,频繁触发函数,节流,每隔 500ms 就执行一次。防抖,则不管调动多少次方法,在2s后,只会执行一次

如下图所示:
在这里插入图片描述


三、应用场景

防抖在连续的事件,只需触发一次回调的场景有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流在间隔一段时间执行一次回调的场景有:

  • 滚动加载,加载更多或滚到底部监听
  • 搜索框,搜索联想功能

希望本文能够对您有所帮助!如果您有任何问题或建议,请随时在评论区留言联系 章挨踢(章IT)
谢谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA中git的使用和代码对比神器Beyond Compare

和多同学idea配置好了&#xff0c;但是使用却不知道怎么使用。 我这里说说idea中使用的几招常用操作。如&#xff1a;提交&#xff0c;拉取&#xff0c;推送&#xff0c;合并&#xff0c;取消合并&#xff0c;撤回本地提交。 以及一些刚接触idea使用git的怕把公司代码搞砸了的同…

Spring cloud智慧工地信息平台管理系统源码

目录 报警统计 实时报警列表 工程进度 劳务信息 隐患信息 施工安全管理 人员证书管理 专项安全方案 安全方案审批 隐患排查管理 安全检查统计 危险源Top10 整改超时预警 检查问题数量统计 安全隐患趋势 安全日志管理 视频监控查看 视频回放 AI危险源识别 AI应用总览 AI设备 机械…

Vue3的v-model

目录 基本用法 底层机制 v-model 的参数 多个 v-model 绑定 处理 v-model 修饰符 带参数的 v-model 修饰符 例子 总结&#xff1a;Vue 3 中的 v-model 指令与 Vue 2 中的 v-model 相比有一些变化和改进。最显著的变化是&#xff0c;在 Vue 3 中&#xff0c;v-model 可以…

TypeScript(四) 运算符

1. 运算符 1.1. 描述 运算符用于执行程序代码运算。 1.2. 运算符主要包括&#xff1a; &#xff08;1&#xff09;算术运算符 &#xff08;2&#xff09;逻辑运算符 &#xff08;3&#xff09;关系运算符 &#xff08;4&#xff09;按位运算符 &#xff08;5&#xff09;赋值…

R语言【taxlist】——print_name():为发表文章准备可用的格式化名称

Package taxlist version 0.2.4 Description 在撰写关于生物多样性的文章时&#xff0c;可以使用名称自动插入到文件中&#xff0c;包括学名不同元素的典型斜体格式。函数print_name既可以应用于 Markdown 文档&#xff0c;也可以应用于图形。在 Rmarkdown 文档中&#xff0c;…

linux中配置文件目录为什么用etc来命名

在早期的 Unix 系统中&#xff0c;/etc 目录的名称确实来源于单词 “etcetera” 的缩写&#xff0c;最初意味着 “其他”&#xff0c;用来存放杂项或者不属于其他特定目录的文件。然而&#xff0c;随着时间的推移&#xff0c;/etc 目录的用途逐渐演变并专门化。 在现代的 Linux…

houdini relate graph

此图来于网络&#xff1a;如有冒犯敬请告之&#xff0c;侵删 类知识图谱效果 wiki graph d3.js&#xff1b; python d3blocks 1.使用算法模拟动态效果&#xff0c;运动形态&#xff08;计算量小&#xff0c;实现 2.wire solver &#xff08; 3.使用刚体&#xff0c;柔体&…

Pytest与unittest区别

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

如何实现Win系统ssh连接Ubuntu使用vscode远程敲代码

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接…

Unity 迭代器模式(实例详解)

文章目录 简介**实例1&#xff1a;遍历数组****实例2&#xff1a;自定义迭代器类****实例3&#xff1a;异步加载资源****实例4&#xff1a;游戏关卡序列****实例5&#xff1a;无限生成敌人** 简介 在Unity中&#xff0c;虽然不直接使用迭代器模式的原始定义&#xff08;即设计…

EasyExcel通用导入 | 简单封装

0. 前言&#xff1a;1. 基本思路&#xff1a;2. 调用代码&#xff1a; 0. 前言&#xff1a; 之前做了好几个导入&#xff0c;用EasyExcel每次都要定义监听器去处理&#xff0c;就想能不能做个通用的方式&#xff0c;如下 1. 基本思路&#xff1a; 导入无非主要就是参数校验和数…

代码随想录刷题笔记-Day14

1. 对称二叉树 101. 对称二叉树https://leetcode.cn/problems/symmetric-tree/给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root […

深度解析指针与数组:探索内存管理的艺术

目录 1.数组名的理解 sizeof(数组名)&#xff0c;sizef中单独放数组名&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小&#xff0c;单位是字节 &数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址 (整个数组的地…

【Java程序设计】【C00179】基于SSM的电影在线购票管理系统(论文+PPT)

基于SSM的电影在线购票管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的电影在线购票管理系统 本系统分为前台用户和后台管理员2个功能模块。 前台用户&#xff1a;当游客打开系统的网址后&#xff0c;首先看到…

AR眼镜_ar智能眼镜显示方案|光学方案

AR眼镜是一种智能眼镜&#xff0c;能够将虚拟现实和现实世界相结合&#xff0c;使人们能够在日常生活中体验和参与虚拟现实。然而&#xff0c;AR智能眼镜的制造成本高&#xff0c;开发周期长。要实现AR眼镜的各项功能&#xff0c;需要良好的硬件条件&#xff0c;而AR智能眼镜的…

Mac忘记本机MySql密码怎么办?

Mac忘记本机MySql怎么办&#xff1f; 1.打开系统偏好设置 2.打开Mysql 3.停止服务 4.直接初始化服务上图有一个初始化数据库 5.输入8位密码确认 6.重启服务

如何使用docker compose安装APITable并远程访问登录界面

文章目录 前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 …

Java RC4加密算法

一、RC4加密算法 在密码学中&#xff0c;RC4&#xff08;来自Rivest Cipher 4的缩写&#xff09;是一种流加密算法&#xff0c;密钥长度可变。它加解密使用相同的密钥&#xff0c;因此也属于对称加密算法。 百度百科 - RC4&#xff1a;https://baike.baidu.com/item/RC4/34545…

DS:经典算法OJ题(1)

创作不易&#xff0c;友友们给个三连呗&#xff01;&#xff01; 本文为经典算法OJ题练习&#xff0c;大部分题型都有多种思路&#xff0c;每种思路的解法博主都试过了&#xff08;去网站那里验证&#xff09;是正确的&#xff0c;大家可以参考&#xff01;&#xff01; 一、移…

数据写入HBase(scala)

package sourceimport org.apache.hadoop.hbase.{HBaseConfiguration, TableName} import org.apache.hadoop.hbase.client.{ConnectionFactory, Put} import org.apache.hadoop.hbase.util.Bytesobject ffff {def main(args: Array[String]): Unit {//hbase连接配置val conf …