深入理解JS中的防抖&节流

66 阅读2分钟

在Web开发中,防抖(Debouncing)和节流(Throttling)是两种常用的优化技术,用于提高页面性能和用户体验。它们通过限制函数执行的频率来减少计算资源的消耗,尤其是在处理频繁触发的事件时,如窗口大小调整、滚动、键盘输入等。

1、防抖(Debouncing)

防抖技术的核心思想是在事件频繁触发的情况下,只有在事件触发的一段时间后没有再次触发事件时,才执行目标函数。如果在这段时间内事件再次被触发,则重新计时。

1.1、应用场景

  • 输入框实时搜索优化
  • 窗口大小调整(resize)事件处理
  • 按钮提交事件(防止多次点击)

1.2、实现示例

const debounce = (func, wait) => {
    let timeout;
    return function() {
        const context = this;
        const args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            func.apply(context, args);
        }, wait);
    };
}

2、节流(Throttling)

节流技术的核心思想是在一定时间内只执行一次目标函数。即使在这段时间内事件被多次触发,目标函数也只会被执行一次。

2.1、应用场景

  • 滚动事件处理(如无限滚动加载或滚动监听)
  • 动画的控制(如避免动画的过度执行)

2.2、实现示例

节流的实现方式有多种多样的,下面介绍几种方式

方案一:基于setTimeout的方式,n个wait周期,执行n次。这种方案有个缺点,最后一个周期内的响应可能会无法被处理

const throttle = (func, wait) => {
    let inThrottle;
    return function() {
        const args = arguments;
        const context = this;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, wait);
        }
    };
}

方案二:基于时间计算实现,相对全面一些,n个wait周期,执行 n + 1 次,确保了最后一个周期的事件也能响应

const throttle = (fn,wait)=>{
    let last ,timer
    return function(){
        let now = Date.now()
        if(last && now < last + wait){
            clearTimeout(timer)
            timer = setTimeout(()=>{
                last = now
                fn.apply(this,arguments)
            },delay)
        }else{
            last = now
            fn.apply(this,arguments)
        }
    }
}

3、防抖与节流的选择

  • 当你希望某些代码在事件停止触发后只执行一次时,使用防抖。
  • 当你希望某些代码不管事件触发多少次,都以一定的频率限制执行时,使用节流。

4、结论

防抖和节流是两种重要的前端性能优化技术。它们通过减少事件处理函数的执行频率,帮助避免页面的卡顿和性能问题。在实际开发中,合理选择和使用防抖与节流,可以显著提升用户体验和应用性能。