原生Javascript 实现防抖动/节流方法

为什么需要防抖和节流?

在一些高频率事件触发的场景下我们不希望对应的事件处理函数多次执行,以免造成性能上的浪费以及用户的体验不佳。

背景:

滚动事件、输入的模糊匹配、轮播图的切换、点击操作等……由于浏览器默认情况下都会有自己的监听事件间隔(4-6ms),如果检测到多次事件的监听执行,那么就会造成不必要的资源浪费。

下面以高频操作为我们业务中需要进行防抖和节流处理的方法代名词,介绍一下防抖和节流的区别。

防抖:

对于这个高频操作来说,我们只希望识别一次操作,可以认为是第一次或者是最后一次操作

节流:

对于高频操作,我们可以自己来设置频率,让本来会执行很多次的事件触发,按着我们设置的频率减少触发的次数。

综上我们可以看出,防抖和节流最大的区别就是防抖只让事件触发一次,而节流是减少事件触发的频率,可以多次触发。下面是我写的防抖和节流的方法代码,可以引用在项目中直接使用。

ps:方法不唯一,大佬勿喷^_^

防抖动代码:

/**
 * handle 为需要防抖的函数
 * wait 为执行等待时间
 * immediate true为第一次执行 false为最后一次执行
 */
function myDebounce(handle, wait, immediate) {
    if(typeof handle !== 'function') throw new Error('handle must be an function')
    if(typeof wait === 'undefined') wait = 300
    if(typeof wait === 'boolean') { // 可以不传时间参数
        immediate = wait
        wait = 300
    }
    if(typeof immediate !== 'boolean') immediate = false
    let timer = null // 接收计时器
    return function proxy(...args) {// 传入所有参数
        let self = this
        let init = immediate && !timer
        clearTimeout(timer)
        timer = setTimeout(() => {
            timer = null
            !immediate ? handle.call(self, ...args) : null
        }, wait)
        // 如果当前传递进来的immediate为true,我们需要立即执行
        // 如果想要实现只在第一次执行,那么需要加上timer为null作为判断
        // 因为只要timer为null,就意味着没有更多次事件触发
        init ? handle.call(self, ...args) : null
    }
}

节流代码:

/**
 * 节流:这里的节流指的就是在自定义的一段时间内让事件进行触发
 * handle 需要节流的事件
 * wait 自定义时间间隔 
 * 假设当前在某时间间隔内执行了一次proxy,我们就可以用这个时间渐趋上一次执行的时间(首次为0),此时就会有一个时间差
 * 前置条件就是我们自己定义了一个wait
 * wait - (now - previous)即我们重新定的执行时间间隔
 * 如果interval大于0,则意味着这是一个高频触发,如果小于0,那我们就可以直接执行
 */
function myThrottle(handle, wait) {
    if(typeof handle !== 'function') throw new Error('handle must be an function')
    if(typeof wait === 'undefined') wait = 500
    let timer = null
    let previous = 0 // 定义变量记录上一次执行时的时间
    return function proxy(...args) {
        let self = this
        let now = new Date() // 定义变量记录当前次执行的时间点
        let interval = wait - (now - previous)

        if(interval <= 0) {
            clearTimeout(timer)
            timer = null
            handle.call(self, ...args)
            previous = new Date()
        } else if(!timer) { // 如果系统中已经有一个定时器,我们就不需要再开启一个计时器     
            timer = setTimeout(() => {
                clearTimeout(timer)
                timer = null
                handle.call(self, ...args)
                previous = new Date()
            }, interval);
        }
    }
}

以上就是我总结的防抖动和节流以及对应代码啦,欢迎大家提出宝贵意见。

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值