用游戏来理解函数防抖和节流——拒绝“八股文”

533 阅读3分钟

背景

之前被大篇幅的解释搞得懵懵的,后来在玩游戏的过程中找到了防抖和节流的区别,大家一起看看吧

防抖和节流的区别

游戏理解逻辑理解
防抖类似王者荣耀/英雄联盟等MOBA类游戏中的回城,重复触发只执行最后一次一段时间内多次触发,只执行最后一次
节流类似游戏中的技能冷却,施放技能后一段时间内再次施放无效一段时间内多次触发,只执行第一次

防抖

防抖(debounce)是指延迟执行函数,在连续触发事件时只执行一次,并且是在最后一次触发事件之后一段时间内执行。例如,当用户调整浏览器窗口大小时,我们可以在用户停止调整大小后一段时间再执行相关操作,从而减少因频繁触发事件而引起的性能问题。

实现

下面是一个常见的函数防抖实现方式:

function debounce(func, delay) {
    let timer = null;
    return function() {
        const that = this;
        clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(that, arguments);
        }, delay);
    };
}

上述代码中,func 表示要执行的函数,delay 表示延迟执行的时间。在返回的函数中,我们首先清除之前设置的定时器,然后重新设置一个新的定时器,等待一段时间后再调用原始函数。

使用场景

使用函数防抖优化窗口大小变动:

window.addEventListener('resize', debounce(() => {
    console.log('窗口大小已改变!');
}, 500));

在上面的例子中,resize 事件触发时将执行传入的函数,但是由于使用了函数防抖,所以只有用户在调整窗口大小之后停止了一段时间后才会真正执行函数。

节流

函数节流(throttle)是指在一定时间内最多执行一次函数,在连续触发事件时,函数不会立即执行,而是在指定的时间间隔之后执行。例如,在用户滚动页面时,我们可以限制函数的执行频率,确保页面的滑动流畅度。

实现

function throttle(func, delay) {
    let time = null;
    return function() {
        if (timer) {
            return;
        }
        const that = this;
        func.apply(that, arguments);
        timer = setTimeout(() => {
            clearTimeout(timer);
            timer = null;
        }, delay);
    }
}

上述代码中,func 表示要执行的函数,interval 表示指定的时间间隔。在返回的函数中,我们首先判断当前是否已经设置了定时器,如果没有则创建一个新的定时器,并在指定时间间隔后执行函数。如果当前已经设置了定时器,则忽略该事件。

使用场景

使用函数节流优化滚动事件:

window.addEventListener('scroll', throttle(() => {
    console.log('滚动条正在滚动!');
}, 200));

在上面的例子中,scroll 事件触发时将执行传入的函数,但是由于使用了函数节流,所以每次滚动事件被触发时,函数最多只会执行一次,并且至少要等待 200 毫秒才会再次触发。

后语

在前端开发中,我们经常会遇到一些需要频繁触发事件的场景,例如窗口大小变动、滚动条滚动等等。而随着浏览器性能的提升,这些事件的触发频率也会越来越高,导致页面性能受到影响,甚至出现卡顿的情况。为了解决这个问题,我们可以借助函数防抖函数节流的思想来优化页面性能

我是前端霸哥,愿你的代码中没有bug
写的不好的地方,欢迎各位小伙伴批评指正