JS中的debounce与throttle(防抖与节流)

1. 简介

防抖debounce与节流throttle是在一些执行频率较高的交互或事件处理中的性能优化

场景一:输入框获取到内容自动请求获取数据

场景二:拖动窗口变大或者缩小

在这些连续交互变化的场景中,若不加防抖或者节流操作,会导致事件频发,浪费性能,加上防抖节流操作后,事件就可以等待用户操作完触发,这样就节省了很多性能。

2. 防抖与节流的对比

debounce

debounce 有一个等待时长,若在等待时间内再次调用了函数,则取消上一个定时器,新建一个定时器重新计时

适用场景:input、keyup、keydown等事件,或者某个需要防止用户多次点击的场景。

在lodash库中,并没有取消、新建等时期的做法,它是用时间来判断的

代码实现:

function debounce(fn, wait) {
    let callback = fn;    
    let timerId = null;

    function debounced() {
        // 保存作用域
        let context = this;
        // 保存参数,例如 event 对象
        let args = arguments;        

        clearTimeout(timerId);        
        timerId = setTimeout(function() {            
            callback.apply(context, args);
        }, wait);
    }
    
    // 返回一个闭包
    return debounced;         
}

// test
let resizeFun = function(e) {
    console.log('resize');
};
window.addEventListener('resize', debounce(resizeFun, 500));

什么是闭包?
闭包有三步:
第一,外层函数嵌套内层函数;
第二, 内层函数使用外层函数的局部变量;
第三,把内层函数作为外层函数的返回值! 经过这样的三步就可以形成一个闭包! 闭包就可以在全局函数里面操作另一个作用域的局部变量!

闭包的作用?
闭包既能重复使用局部变量,又不污染全局!

throttle

throttle也有一个等待时长,在用户持续触发事件的过程中,函数每隔一段时间都会执行一次函数,若事件处理函数没有处理完时事件依旧在触发,则它会忽略下次调用该函数的请求。

适用场景:窗口变化、鼠标移动事件

代码实现:throttle相对于debounce最大区别就是不会取消上一次函数的执行

相同点

都是利用函数延迟执行来实现效果,可以理解为使用了setTimeout

举个🌰:
使用 lodash 处理 resize 事件时,在wait 参数不是非常小的情况下:
debounce的话,会在用户停止改变浏览器窗口大小时触发,也就是只是在最后触发一次。
throttle的话,会在用户改变浏览器窗口大小的过程中,每隔一段时间触发一次。

其实在 lodash 的实现中: throttle 就是一个定义了最大等待时长的 debounce。

function throttle(fn, wait) {
    let callback = fn;    
    let timerId = null;

    // 是否是第一次执行
    let firstInvoke = true;

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

        // 如果是第一次触发,直接执行
        if (firstInvoke) {
            callback.apply(context, args);
            firstInvoke = false;
            return ;
        }

        // 如果定时器已存在,直接返回。        
        if (timerId) {
            return ;
        }

        timerId = setTimeout(function() {  
            // 注意这里 将 clearTimeout 放到 内部来执行了
            clearTimeout(timerId);
            timerId = null;

            callback.apply(context, args);
        }, wait);
    }
    // 返回一个闭包
    return throttled;
}
// test
let resizeFun = function(e) {
    console.log('resize');
};
window.addEventListener('resize', throttle(resizeFun, 500));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值