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

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 最近和前端的小伙伴们,在讨论面试题的时候。谈到了函数防抖和函数节流的应用场景和原理。于是,想深入研究一下两者...
    youthcity阅读 23,623评论 5 78
  • 手写防抖函数 debounce 和节流函数 throttle 本文参考:深入浅出节流函数 throttle深入浅出...
    请叫我大苏阅读 7,147评论 1 4
  • 防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案 debounce,去抖动。策略是当事件被触发时,设定一个...
    皇甫圣坤阅读 382评论 0 0
  • 一、什么是防抖和节流?为什么用? |--引入防抖和节流解决的问题:当一个函数被频繁、无限制的被调用的时候,会加...
    stillpeng阅读 2,739评论 0 0
  • 概念 函数防抖(debounce) 当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执...
    yuanjiex阅读 644评论 0 1