JavaScript 节流(Throttle)与防抖(Debounce)原理及使用场景

叶初
叶初
发布时间:2026-10-15| 6人浏览过
原创

在前端开发中,面对频繁触发的事件(如窗口调整、滚动、输入框打字),直接执行处理函数会导致性能瓶颈。节流(Throttle)和防抖(Debounce)是解决此类问题的两大核心策略。本文将深入解析两者的区别,并提供基于原生 JavaScript 的实现代码与应用指南。

结果与目标

通过理解并应用节流与防抖,我们可以有效控制函数的执行频率,避免页面卡顿,提升资源利用率。具体目标是:

  • 节流:确保函数在规定时间内最多执行一次,保持持续的节奏响应。
  • 防抖:确保函数在短时间内多次调用时仅执行最后一次,避免无效计算。

准备条件

以下实现均基于原生 JavaScript (ES5/ES6),无需引入任何第三方库。代码适用于浏览器环境或 Node.js 环境,主要涉及闭包、setTimeout 及 this 上下文绑定等技术点。

真实操作顺序

第1步:实现节流函数 Throttle

目的:解决事件高频率触发导致函数执行次数过多的问题。例如鼠标移动、窗口 resize 等场景,我们希望每隔一段时间才执行一次业务逻辑,而不是每次触发都执行。

入口/参数:func (要执行的函数), threshold (间隔时间, 默认100ms), alt (可选,间隔内触发的备用回调)。

动作:利用闭包记录上次执行时间 (last)。当新调用发生时,计算当前时间与上次执行时间的差值。如果小于阈值,则可能执行备用逻辑或直接返回;如果大于等于阈值,则执行主函数并更新时间戳。

var throttle = function (func, threshold, alt) {
    var last = Date.now();
    threshold = threshold || 100;
    return function () {
        var now = Date.now();
        if (now - last < threshold) {
            // 如果在间隔内,且提供了替代函数,则执行替代函数
            if (alt) {
                alt.apply(this, arguments);
            }
            return;
        }
        // 执行主函数并更新最后执行时间
        last = now;
        func.apply(this, arguments);
    };
};

第2步:实现防抖函数 Debounce

目的:解决连续快速触发时,只有最后一次有效的问题。典型场景包括搜索框联想、表单提交验证,用户停止输入后才请求数据。

入口/参数:func (要执行的函数), threshold (延迟时间), execASAP (是否立即执行,即首次调用时是否执行)。若为 false,则为标准的“静默后执行”;若为 true,则为“首次立即执行,后续静默”。通常我们使用标准防抖(execASAP=false)。

动作:利用 setTimeout 设置一个定时器。每次调用时先清除上一次的定时器(clearTimeout),防止执行之前的回调。然后重新设置一个新的定时器。只有当用户停止调用超过 threshold 时间后,定时器才会到期并执行 func。

var debounce = function (func, threshold, execASAP) {
    var timeout = null;
    threshold = threshold || 100;
    return function () {
        var self = this;
        var args = arguments;
        
        // 定义延迟执行的函数
        var delayed = function () {
            if (!execASAP) {
                func.apply(self, args);
            }
            timeout = null;
        };
        
        // 如果存在定时器,则清除它,重新开始计时
        if (timeout) {
            clearTimeout(timeout);
        } else if (execASAP) {
            // 如果是立即执行模式,第一次调用直接执行
            func.apply(self, args);
        }
        
        // 设置新的定时器
        timeout = setTimeout(delayed, threshold);
    };
};

第3步:测试验证效果

目的:通过模拟高频随机延迟的调用,观察节流和防抖的实际输出日志,确认函数执行次数是否符合预期。

测试逻辑:创建一个日志函数,记录距离起始时间的毫秒数。分别包裹节流和防抖函数,循环 10 次,每次使用随机时间延迟执行。

var test = function (wrapper, threshold) {
    var log = function () {
        console.log(Date.now() - start);
    };
    // 包装函数
    var wrapperedFunc = wrapper(log, threshold);
    var start = Date.now();
    var arr = [];
    
    // 生成待执行的函数数组
    for (var i = 0; i < 10; i++) {
        arr.push(wrapperedFunc);
    }
    
    // 随机延迟执行
    var i = 10;
    while(i > 0) {
        var random = Math.random() * 1000; // 0-1000ms 的随机延迟
        console.log('index: ' + (i-1));
        console.log('random delay: ' + random + 'ms');
        setTimeout(arr[--i], random);
    }
};

// 测试防抖:1秒内多次调用,仅最后一次有效
console.log("--- Debounce Test ---");
test(debounce, 1000);

// 测试节流:每1秒最多执行一次
console.log("\n--- Throttle Test ---");
test(throttle, 1000);

完成判断

节流的完成状态:观察控制台,你会看到输出的时间戳间隔均匀,大约每隔 threshold 毫秒打印一次。即使调用了 10 次,最终执行次数也远少于 10 次。

防抖的完成状态:观察控制台,在密集调用期间没有输出,直到所有调用结束并等待 threshold 时间后,才打印一次时间戳。这证明函数只在用户动作静止后被执行。

原文有依据的排错

  • 关于 this 上下文丢失:在上述防抖代码中,特意提取了 self = this,因为 delayed 函数内部的 this 会指向全局对象或 undefined (strict mode)。必须确保调用主函数时使用正确的上下文。
  • 关于立即执行:防抖函数中的 execASAP 参数常用于导航栏吸顶等场景,希望用户在进入区域时立刻触发一次,之后再频繁调整尺寸时不再重复触发。若不传此参数,默认遵循传统的“离开后触发”逻辑。

简要总结

节流适合需要持续响应但降低频率的场景,如滚动加载、窗口缩放;防抖适合需要最终结果且忽略中间过程的场景,如搜索提示、按钮防止重复点击。正确选择算法能显著优化 Web 应用性能。以上就是 JavaScript 节流与防抖应用介绍的详细内容,更多关于 JavaScript 前端性能优化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。