节流防抖函数

节流防抖函数概念 debounce 防抖 throttle 节流节流节流的原理很简单 如果你持续触发事件 每隔一段时间 只执行一次事件 根据首次是否执行以及结束后是否执行 效果有所不同 实现的方式也有所不同 我们用 leading 代表首次是否执行 trailing 代表结束后是否再执行一次 关于节流的实现 有两种主流的实现方式 一种是使用时间戳 一种是设置定时器 使用时间戳 让我们来看第一种方法 使用时间戳 当触发事件的时候 我们取出当前的时间戳 然后减去之前的时间戳 最一开始值设为 0 如

概念:

debounce 防抖 、 throttle 节流

节流
节流的原理很简单:
如果你持续触发事件,每隔一段时间,只执行一次事件。
根据首次是否执行以及结束后是否执行,效果有所不同,实现的方式也有所不同。
我们用 leading 代表首次是否执行,trailing 代表结束后是否再执行一次。








关于节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。

使用时间戳:

让我们来看第一种方法:使用时间戳,当触发事件的时候,我们取出当前的时间戳,然后减去之前的时间戳(最一开始值设为 0 ),如果大于设置的时间周期,就执行函数,然后更新时间戳为当前的时间戳,如果小于,就不执行。

———————————————————————————————————————————————————————————————————————

防抖函数分为非立即执行版和立即执行

  • 非立即执行

非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

 function debounce(func, wait) { 
    let timeout; return function () { 
    let context = this; let args = arguments; if (timeout) clearTimeout(timeout); timeout = setTimeout(() => { 
    func.apply(context, args) }, wait); } } 

我们依旧使用上述绑定 mousemove 事件的例子,通过上面的防抖函数,我们可以这么使用

content.onmousemove = debounce(count,1000); 

在这里插入图片描述
可以看到,在触发事件后函数 1 秒后才执行,而如果是在触发事件后的 1 秒内又触发了事件,则会重新计算函数执行时间。

上述防抖函数的代码还需要注意的是 this 和 参数的传递

let context = this; let args = arguments; 

防抖函数的代码使用这两行代码来获取 this 和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。

  • 立即执行版本
 function debounce(func,wait) { 
    let timeout; return function () { 
    let context = this; let args = arguments; if (timeout) clearTimeout(timeout); let callNow = !timeout; timeout = setTimeout(() => { 
    timeout = null; }, wait) if (callNow) func.apply(context, args) } } 

立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。

双剑合璧版:

/ * @desc 函数防抖 * @param func 函数 * @param wait 延迟执行毫秒数 * @param immediate true 表立即执行,false 表非立即执行 */ function debounce(func,wait,immediate) { 
    let timeout; return function () { 
    let context = this; let args = arguments; if (timeout) clearTimeout(timeout); if (immediate) { 
    var callNow = !timeout; timeout = setTimeout(() => { 
    timeout = null; }, wait) if (callNow) func.apply(context, args) } else { 
    timeout = setTimeout(function(){ 
    func.apply(context, args) }, wait); } } } 

对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版。

时间戳版:

function throttle(func, wait) { 
    let previous = 0; return function() { 
    let now = Date.now(); let context = this; let args = arguments; if (now - previous > wait) { 
    func.apply(context, args); previous = now; } } } 

使用方式如下

content.onmousemove = throttle(count,1000); 

在这里插入图片描述
可以看到,在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。

定时器版:

function throttle(func, wait) { 
    let timeout; return function() { 
    let context = this; let args = arguments; if (!timeout) { 
    timeout = setTimeout(() => { 
    timeout = null; func.apply(context, args) }, wait) } } } 

我们应该可以很容易的发现,其实时间戳版和定时器版的节流函数的区别就是,时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。

同样地,我们也可以将时间戳版和定时器版的节流函数结合起来,实现双剑合璧版的节流函数。

双剑合璧版:

/ * @desc 函数节流 * @param func 函数 * @param wait 延迟执行毫秒数 * @param type 1 表时间戳版,2 表定时器版 */ function throttle(func, wait ,type) { 
    if(type===1){ 
    let previous = 0; }else if(type===2){ 
    let timeout; } return function() { 
    let context = this; let args = arguments; if(type===1){ 
    let now = Date.now(); if (now - previous > wait) { 
    func.apply(context, args); previous = now; } }else if(type===2){ 
    if (!timeout) { 
    timeout = setTimeout(() => { 
    timeout = null; func.apply(context, args) }, wait) } } } } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/202468.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午7:04
下一篇 2026年3月20日 上午7:04


相关推荐

  • 被面试官问懵B了,十亿级数据ES搜索怎么优化?

    面试题 es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊? 面试官心理分析 这个问题是肯定要问的,说白了,就是看你有没有实际干过 es,因为啥?其实 es 性能并没有你想…

    2021年6月22日
    133
  • php工厂模式

    php工厂模式定义:我们只需要提供一个创建对象实例的功能,而无需关心其具体实现,被创建实例的类型可以是接口、抽象类,也可以是具体的类。一、简单工厂模式(平时开发中基本上简单工厂模式就够用了)说明: Api:定义客户所需要的功能接口(后面具体实现的类基本上就根据这个来) Impl:具体实现Api的实现类,一般有多个, Factory:工厂,选择合适的实现类来创建Api接…

    2022年7月25日
    14
  • esp-idf的内存管理——tlsf算法

    esp-idf的内存管理——tlsf算法目录1最初还不是tlsf2为什么要引入tlsf3idf中使用的tlsf算法的设计与实现4源码走读参考1最初还不是tlsf2为什么要引入tlsf3idf中使用的tlsf算法的设计与实现4源码走读参考[1]半文钱的博客[2]upstream所在的github地址注意事项放到内存调试去说:用户需要关注的:内存的硬件特性(caps)内存的访问速度内存是否支持原子操作内存是否可以由CPU直接访问用户在使用时:用户自己也要对自己的应用需要使用的内存做一些安排,有的内存比

    2022年6月29日
    27
  • Java集合容器面试题(2020最新版)「建议收藏」

    Java集合容器面试题(2020最新版)「建议收藏」文章目录集合容器概述什么是集合集合的特点集合和数组的区别使用集合框架的好处常用的集合类有哪些?List,Set,Map三者的区别?List、Set、Map是否继承自Collection接口?List、Map、Set三个接口存取元素时,各有什么特点?集合框架底层数据结构哪些集合类是线程安全的?Java集合的快速失败机制“fail-fast”?怎么确保一个集合不能被修改?Collection…

    2022年6月14日
    29
  • windows程序设计第五版_windows程序开发

    windows程序设计第五版_windows程序开发[声明]HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor);[说明]用指定的样式、宽度和颜色创建一个画笔[参数表]nPenStyle —— Long,指定画笔样式,可以是下述常数之一PS_SOLID画笔画出的是实线PS_DASH画笔画出的是虚线(nWidth必须不大于1)PS_DOT画笔画出的是点线(…

    2022年8月18日
    15
  • SQL的多表查询

    SQL的多表查询

    2021年7月20日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号