JavaScript防抖与限流详解

更新于 2025-10-03

在前端开发中,防抖(debounce)限流(throttle)是两个常见的性能优化技巧,主要用于控制高频率事件的触发,比如滚动、输入、窗口缩放等。

下面分别介绍这两个方法,并对它们的区别进行直观讲解。


一、防抖(Debounce)

防抖的作用:
防抖的核心思想是在事件被频繁触发时,只在最后一次触发后过一段时间才执行目标函数。

如果在这段时间内又触发了事件,则重新计时。

这意味着,只会在事件停止触发后,执行最后一次的操作。

实现代码:

function debounceFunction(fn, timeout) {
    var timer = 0;
    return function() {
        if (timer) window.clearTimeout(timer);
        var args = arguments, that = this;
        timer = window.setTimeout(function() {
            fn.apply(that, args);
        }, timeout);
    };
}

使用示例:

var func = debounceFunction(function(name) {
    console.log(name);
}, 500);

func('test1');
func('test2');
func('test3');
func('test4');
// 每调用一次都重置 timer,并设置新的 timeout。
// 在 500ms 内连续多次调用,只会执行最后一次(即 test4)。

直观说明:
比如你将 func 绑定到一个按钮的点击事件上,每次点击都会重新计时。

如果你不断点击,目标函数可能永远不会被执行;只有最后一次点击后等待够了 timeout,才会真正执行。


二、限流(Throttle)

限流的作用:
限流的核心思想是在高频事件触发时,按照设定的时间间隔(timeout)来执行目标函数。

即使事件被频繁触发,也只会按照固定节奏执行,而不会漏掉首次触发。

实现代码:

function throttleFunction(fn, timeout) {
    var last_exec = 0;
    return function() {
        var now = +new Date();
        if (now - last_exec < timeout) return;
        last_exec = now;
        fn.apply(this, arguments);
    };
}

使用示例:

var func = throttleFunction(function(name) {
    console.log(name);
}, 500);

func('test1');
func('test2');
setTimeout(function() {
    func('test3');
}, 600);
// 这里 func('test2') 不会被执行,因为距离上一次执行未超过 500ms

直观说明:
同样将 func 绑定到按钮点击事件上,无论你多快点击,目标函数第一次一定会执行。

之后每隔 timeout(比如 500ms)才有机会再次执行,期间多次点击只会被忽略。


三、区别总结

  • 防抖:高频触发时,只有最后一次会被执行。不断触发可能导致目标函数永远不执行。
  • 限流:高频触发时,首次会立即执行,之后每隔一段时间执行一次,不会漏掉第一次。

场景举例:

  • 防抖适合输入框实时搜索、窗口 resize 结束后处理等场景。
  • 限流适合滚动监听、页面拖拽等场景,确保定期响应。

总结一句话:

防抖关注“最后一次”,限流关注“每隔一段时间”。

浙ICP备19039918号-1