文章

高阶函数:函数节流

函数节流(Throttling) 是一种优化技术,用于限制函数的调用频率,确保在指定的时间间隔内只会执行一次函数。函数节流通常用于处理高频触发的事件,如滚动、调整窗口大小、按键等,以减少执行频率,降低资源消耗。

函数节流的工作原理

函数节流的核心思想是在给定的时间间隔内,只允许函数执行一次,超出的触发会被忽略。例如,如果设定的时间间隔为 100ms,那么无论在这段时间内触发多少次事件,函数都只会执行一次。

节流的实现方式

函数节流的常见实现方式是通过 setTimeout 来控制函数的执行节奏。下面是一个实现函数节流的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function throttle(fn, delay) {
    let lastExecutionTime = 0;  // 记录上一次执行的时间

    return function(...args) {
        const now = Date.now();  // 获取当前时间

        // 如果当前时间距离上次执行时间超过了设定的时间间隔
        if (now - lastExecutionTime >= delay) {
            lastExecutionTime = now;  // 更新最后执行时间
            fn.apply(this, args);  // 执行目标函数
        }
    };
}
</script>

假设我们有一个滚动事件,并希望在用户滚动时,控制函数执行的频率,以减少不必要的重复调用:

1
2
3
window.addEventListener('scroll', throttle(() => {
    console.log('Scroll event triggered');
}, 100));  // 设置100ms的时间间隔

在这个例子中,无论滚动事件多频繁触发,throttle 函数都会确保目标函数 console.log 至多每隔 100ms 执行一次。

优化点:使用 setTimeout 实现节流

除了上述实现方式,我们还可以使用 setTimeout 进行控制。如下:

1
2
3
4
5
6
7
8
9
10
11
12
function throttle(fn, delay) {
    let timer = null;

    return function(...args) {
        if (!timer) {  // 只有在没有定时器的情况下才设置新的定时器
            timer = setTimeout(() => {
                fn.apply(this, args);  // 执行目标函数
                timer = null;  // 清空定时器标记
            }, delay);
        }
    };
}

在该实现中,当触发事件时,如果 timer 不为空,则表示在指定时间间隔内不允许执行,fn 只有在 timer 过期后才能再次执行。和前面的实现类似,这种实现方式也可以很好地控制频繁触发的事件执行频率。

函数节流的使用场景

  1. 滚动事件:在页面滚动过程中可能会触发数百次事件,使用节流可以减少触发频率,例如:在页面滚动时执行懒加载或元素检测。
  2. 窗口调整:窗口大小调整时往往需要重新计算布局、更新内容,节流可以有效减少计算的频率。
  3. 按钮点击:例如点赞、收藏等按钮,节流可以防止用户多次点击造成重复请求。

函数节流与函数防抖的区别

  • 函数节流:限制函数在规定的时间间隔内执行一次。即便多次触发,函数会每隔一段时间就执行一次。
  • 函数防抖:在事件频繁触发的情况下,只在事件停止后的一段时间才执行函数。只要事件不断被触发,函数的执行就会被延迟。

总结

函数节流是优化高频事件执行的有效手段,特别适用于用户滚动、窗口调整等情况,通过在时间间隔内只执行一次函数,降低系统负担并提高性能。

本文由作者按照 CC BY 4.0 进行授权