JavaScript事件防抖与节流的核心实现与应用场景解析

Felix
Felix
发布时间:2026-10-15| 5人浏览过
原创

在处理scroll、resize等高频触发事件时,若直接绑定处理函数,极易引发浏览器性能问题。通过引入防抖(Debounce)和节流(Throttle)机制,可以显著降低函数执行频率。本文将深入解析这两者的核心差异,并提供从基础到高级的完整代码实现,涵盖立即执行、定时器延迟及混合模式,适用于搜索联想、无限滚动加载等多种前端场景。

防抖动(Debounce)的实现

防抖动的主要策略是:规定一个时间间隔,在指定时间内如果再次触发事件,则重新计时。只有当事件停止触发并经过这段延迟后,回调函数才会执行一次。这类似于“合并多次操作为一次”,特别适用于需要等待用户完成连续动作后才响应的场景(如搜索输入框联想)。

第1步:基础防抖实现

目的是将连续的事件调用合并为最后一次调用。通过维护一个定时器,每次事件触发都清除旧定时器并设置新定时器。

// 将会包装事件的 debounce 函数
function debounce(fn, delay) {
  // 维护一个 timer
  let timer = null;
 
  return function() {
    // 通过 ‘this' 和 ‘arguments' 获取函数的作用域和变量
    let context = this;
    let args = arguments;
 
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  }
}

使用示例:当用户滚动容器时,每隔一定时间只记录一次状态。

// 当用户滚动时被调用的函数
function foo() {
  console.log('You are scrolling!');
} 
 
// 在 debounce 中包装我们的函数,过 2 秒触发一次
let elem = document.getElementById('container');
elem.addEventListener('scroll', debounce(foo, 2000));

第2步:支持立即执行的防抖

在某些场景下,我们希望第一次触发时就立即执行,之后如果在延迟期内继续触发则忽略,直到停止触发后再等待延迟周期方可下一次执行。这需要增加 immediate 参数。

function debouce(func,delay,immediate){
    var timer = null;
    return function(){
        var context = this;
        var args = arguments;
        if(timer) clearTimeout(timer); //注意原稿此处变量名为time,已修正为timer
        if(immediate){
            //根据距离上次触发操作的时间是否到达delay来决定是否要现在执行函数
            var doNow = !timer;
            //每一次都重新设置timer,就是要保证每一次执行的至少delay秒后才可以执行
            timer = setTimeout(function(){
                timer = null;
            },delay);
            //立即执行
            if(doNow){
                func.apply(context,args);
            }
        }else{
            timer = setTimeout(function(){
                func.apply(context,args);
            },delay);
        }
    }
}

节流(Throttle)的实现

节流的作用是:无论事件触发多频繁,保证在规定时间内一定执行且只执行一次真正的事件处理函数。与防抖不同,节流强调的是“固定频率执行”。它常用于页面的无限加载场景,确保用户在滚动时每隔一段时间发一次Ajax请求,而不是只在停下时请求。

第3步:基于时间戳的节流

思路是记录上一次执行的时间 prev,每次触发时计算当前时间 now。如果差值大于延迟时间 delay,则执行函数并更新 prev。

var throttle = function(func,delay){
    var prev = Date.now();
    return function(){
        var context = this;
        var args = arguments;
        var now = Date.now();
        if(now-prev>=delay){
            func.apply(context,args);
            prev = Date.now();
        }
    }
}

这种实现的优点是:当高频事件触发时,如果首次触发的间隔足够大,会立即执行;后续每 delay 秒执行一次。缺点是:最后一次触发后不会立即执行,而是可能在一段空闲期后才被处理。

第4步:基于定时器的节流

思路是利用定时器标志位。如果定时器存在,说明正处于冷却期,不执行;如果定时器不存在,则开启定时器并执行逻辑,随后清空定时器以允许下一次触发。

var throttle = function(func,delay){
    var timer = null;
 
    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                func.apply(context,args);
                timer = null;
            },delay);
        }
    }
}

这种实现的缺点是:第一次触发时不会立即执行,而是等待 delay 秒后才执行;结束时可能会多执行一次。适合对实时性要求不高,但要求执行频率上限严格的场景。

第5步:定时器与时间戳混合节流

为了兼顾“立即执行”和“结束前再执行一次”,可以综合使用两种方案。计算剩余时间 remaining,如果未到时间则设定定时器,到了时间则立即执行并重置起始时间。

var throttle = function(func,delay){
    var timer = null;
    var startTime = Date.now();
 
    return function(){
        var curTime = Date.now();
        var remaining = delay-(curTime-startTime);
        var context = this;
        var args = arguments;
 
        clearTimeout(timer);
        if(remaining<=0){
            func.apply(context,args);
            startTime = Date.now();
        }else{
            timer = setTimeout(func,remaining);
        }
    }
}

该实现确保了在每个 delay 时间窗口内一定会执行一次函数,且在事件流结束时能处理最后一次延迟逻辑,是较为严谨的节流方案。

总结与对比

防止一个事件频繁触发回调函数的方式主要分为两类:

  • 防抖动(Debounce):将几次操作合并为一次操作。原理是维护一个计时器,规定在 delay 时间后触发函数,但是在 delay 时间内再次触发的话,就会取消之前的计时器而重新设置。结果是只有最后一次操作能被触发。
  • 节流(Throttle):使得一定时间内只触发一次函数。不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。而防抖动只是在最后一次事件后才触发一次函数(指非立即模式)。其原理是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器或更新基准时间。

以上就是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 算法库。