防抖与节流

1、防抖和节流概述

1-1、防抖(Debounce)

确保在指定的时间间隔内,无论连续触发了多少次事件,只有最后一次事件会在该间隔结束后执行。(触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。)

核心逻辑

  • 重置计时器:每次事件触发时,都会重置计时器。
  • 执行时机:只有在用户停止触发事件指定时间间隔后,才会执行最后一次事件。
  • 举例:

    想象一台自动售货机,里面都是不同价格的商品,当你投入相应的硬币,会自动选择对应商品。但是为了避免还没投完就出商品,售货机设计不是投完立即掉出商品,而是有一个短暂的延迟,在这个延迟期间,如果你再次投入硬币,售货机重新进入延迟,只有当延迟期过后,之前投入硬币才会被处理。这样可以避免因为误操作或快速连续操作导致的错误购买。

// 创建一个防抖函数,它返回一个新的函数,该新函数在指定的 wait 时间后执行 func
function debounce(func, wait) {
    // 保存定时器的引用
    let timeout;
 
    // 返回的函数是用户实际调用的函数,它包含了防抖逻辑
    return function(...args) {
        // 保存当前的 this 上下文
        const context = this;
        console.log(context);  
 
        // 清除之前的定时器,如果存在
        if (timeout) clearTimeout(timeout);  
 
        // 设置一个新的定时器
        // 当指定的 wait 时间过后,将执行 func 函数
        // 并将当前的 this 上下文和参数传入
        timeout = setTimeout(function() {  
            // 执行原始函数,绑定正确的 this 上下文和参数
            func.apply(context, args);  
        }, wait);  
    };
}

当防抖函数被触发时,首先会检查是否已经存在一个timeout(即是否有一个定时器在运行)。
如果存在,表示之前有触发过防抖函数但还未执行func,此时使用clearTimeout清除之前的定时器。
然后,设置一个新的timeout,如果在wait指定的时间内再次触发防抖函数,之前的定时器会被清除并重新设置,这意味着func的执行会被不断推迟。
只有当指定的时间间隔wait内没有再次触发防抖函数时,timeout才会到达,此时会执行原始函数func,并且使用apply方法将存储的context和args传递给它。

1-2、节流(Throttle)

确保在指定的时间间隔内,无论触发了多少次事件,只有第一次事件会被执行,后续事件在这个间隔内都不会执行。(连续触发事件但是在 n 秒中只执行第一次触发函数)。

核心逻辑

  • 单次执行:在时间间隔内只执行一次事件处理函数。
  • 忽略后续触发:在时间间隔内,后续的事件触发将被忽略。
  • 举例:

    想象一个繁忙的十字路口,交通信号灯每60秒变换一次。不论有多少车辆通过,信号灯都不会更快地变换。这就像节流,无论事件触发的频率多高,每个周期内只执行一次。

function throttle(func, limit) {
    let inThrottle = false;
 
    return function(...args) {
        const context = this; // 保存当前的 this 上下文
 
        if (!inThrottle) {
            // 执行传入的函数
            func.apply(context, args);
            inThrottle = true; // 标记为正在节流
 
            // 使用闭包和 setTimeout 来在指定的延迟后重置 inThrottle
            setTimeout(() => {
                inThrottle = false; // 重置节流状态
            }, limit);
        }
    };
}

func:需要被节流的函数。
limit:表示在指定的时间间隔后,func才能再次被执行的时间(以毫秒为单位)。
inThrottle:一个布尔值,用来标记func是否处于可执行状态。
context:保存当前的this上下文,确保在执行func时this指向正确。
args:使用扩展运算符...来收集所有参数,以便将它们传递给func。
setTimeout:在指定的limit时间后执行,将inThrottle重置为false,这样func就可以在下一次调用时被执行了。

2、应用场景

2-1、防抖(Debounce)

搜索框输入:当用户在搜索框中输入文本时,通常会有一些实时搜索建议。使用防抖可以确保只有在用户停止输入一段时间后才触发搜索请求,避免因为快速连续输入而导致的大量请求。

2-2、节流(Throttle)

滚动事件:在处理滚动事件时,如无限滚动加载更多内容,节流可以限制触发事件处理程序的频率,避免过度触发导致性能问题。

3、总结

相同点:


实现机制:两者都可以通过JavaScript的setTimeout函数实现,利用时间延迟来控制回调函数的执行。
性能优化:它们的共同目的都是减少函数的执行频率,以此来提高程序的性能,避免不必要的计算资源消耗。


不同点:


执行时机:

防抖(Debounce):确保在指定的时间间隔结束后执行一次函数。如果在这段时间内多次触发事件,则只有最后一次事件会在延迟后执行函数。
节流(Throttle):确保在指定的时间间隔内最多执行一次函数。无论在这段时间内触发了多少次事件,只有第一次事件会立即执行函数。


应用场景:

防抖:适用于搜索框输入、表单验证等场景,用户完成输入后,才执行相关操作。
节流:适用于滚动事件、按钮点击等,需要在连续事件中合理控制执行频率的场景。


触发逻辑:

防抖:关注一段时间内的连续触发,但只对最后一次操作做出响应。
节流:在一段时间内,无论触发多少次事件,只响应一次。


分辨技巧:

如果您希望在一系列快速操作结束后只执行一次函数,那么使用防抖。
如果您希望在一系列快速操作中合理控制函数的执行频率,那么使用节流。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值