JavaScript防抖和节流--造轮子它不香吗

该篇博文借鉴了前辈的博客,仅用于记录学习
https://www.jianshu.com/p/c8b86b09daf0

在react框架中,给我们提供了防抖和节流的库,可以直接使用,请跳转下方博文
react中的防抖和节流,大佬封装的方法用起来就是爽

防抖和节流

我们经常在开发过程中因为高触发频率,使程序运行产生某些问题,防抖和节流是针对触发频率这类问题的两种解决方案。
在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。

//Html:

<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>

//Script:

let num = 1;
let content = document.getElementById('content');

function count() {
    content.innerHTML = num++;
};
content.onmousemove = count;

防抖(debounce)

触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。这是debounce的基本思想,在后期又扩展了前缘debounce,即执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定。
延迟debounce,是在周期结束时执行,前缘debounce,是在周期开始时执行。但当触发有间断,且间断大于我们设定的时间间隔时,动作就会有多次执行。

  1. 延迟(debounce)
    在这里插入图片描述
content.onmousemove = debounce(count, 500);
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);
            }
        }

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

let context = this;
let args = arguments;

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

2.前缘debounce
在这里插入图片描述

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)
            }
        }

节流(throttling)

连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。与debounce类似,延迟是指 周期结束后执行动作,前缘是指执行动作后再开始周期。
throttling的特点在连续高频触发事件时,动作会被定期执行,响应平滑。

延迟throttling
在这里插入图片描述


content.onmousemove = throttle(count, 500);

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)
               }

           }
       }

前缘throttling
在这里插入图片描述

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;
               }
           }
       }

防抖和节流各有特点,在不同的场景要根据需求合理的选择策略。如果事件触发是高频但是有停顿时,可以选择防抖;在事件连续不断高频触发时,只能选择节流,因为防抖可能会导致动作只被执行一次,界面出现跳跃。
该篇文章参考了多位前辈的总结,如果涉及侵权,请联系我删除。

发布了30 篇原创文章 · 获赞 6 · 访问量 4732

猜你喜欢

转载自blog.csdn.net/EcbJS/article/details/104701118