• 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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

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

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

    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));
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    CEAC 之《企业信息化管理》1
    苯丙氨酸甲酯双三氟甲基磺酰亚胺[PheC1][Tf2N]氨基酸酯离子液体
    面试真题:经典智力题最详汇总
    java-net-php-python-jspm家教信息管理系统演示录像(1)计算机毕业设计程序
    嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理②
    【JAVA基础】String类概述
    工具及方法 - 使用Total Commander来查找重名文件
    【Linux】 yum —— Linux 的软件包管理器
    写csv相关操作
    143. 最大异或对(01字典树)
  • 原文地址:https://blog.csdn.net/NGUP_LEE/article/details/128149326