节流的核心原理是控制函数执行频率,确保在指定时间间隔内最多只执行一次;它通过闭包保存上一次执行时间戳,每次触发时对比当前时间与上次执行时间的差值,仅当差值不小于设定间隔时才执行函数并更新时间戳。

节流的核心原理是控制函数执行频率,确保在指定时间间隔内最多只执行一次。它不是简单地“延迟执行”,而是通过闭包保存上一次执行的时间戳,在每次触发时对比当前时间与上次执行时间的差值,决定是否放行。
闭包保存上次执行时间
节流函数内部定义一个变量(如 lastTime),初始值通常为 0 或 Date.now()。这个变量被闭包捕获,生命周期独立于外部调用,能持续记录上一次成功执行的时间点。
- 每次事件触发时,先获取当前时间戳(Date.now() 或 performance.now())
- 计算与 lastTime 的差值:currentTime - lastTime
- 若差值 ≥ 设定的等待间隔(如 100ms),则执行目标函数,并更新 lastTime = currentTime
- 否则跳过本次调用,不执行也不重置计时
时间戳对比决定是否执行
关键逻辑在于“差值判断”,而非定时器轮询。这意味着:只要两次触发间隔足够长,就立即执行;若连续高频触发,仅保留符合间隔条件的那一次(通常是第一次或最后一次,取决于实现策略)。
宝塔面板11.3.0是一款针对Linux服务器设计的可视化管理工具,通过重构核心模块实现资源占用显著降低,尤其适合低配置服务器环境。它将复杂的命令行操作转化为直观的图形界面,帮助开发者快速完成网站部署、环境配置及日常运维工作,无需专业技术背景即可高效管理服务器。
- 使用 Date.now() 足够满足大多数场景,精度约 1ms
- 对高精度要求(如动画、滚动性能优化),推荐 performance.now(),它返回浮点数毫秒,不受系统时间调整影响
- 注意避免直接用 new Date().getTime(),虽等价但创建对象有轻微开销
常见实现中的“leading”与“trailing”模式
基础时间戳对比默认是“尾部节流”(trailing):仅在间隔达标后执行,可能丢失首次快速触发。若需保证首次立即响应,可引入 leading 标志:
- 首次触发时,若 lastTime === 0,直接执行并记录时间
- 后续触发仍按差值判断,但需额外标记“是否已触发过首次”
- 部分实现会结合定时器实现“首尾兼顾”,但本质仍是时间戳对比 + 状态管理
为什么不用 setInterval 或 setTimeout 堆砌?
单纯靠定时器轮询会带来额外开销和不可控延迟。而时间戳对比是同步瞬时判断,无异步调度、无内存泄漏风险、无定时器清理负担。它轻量、可靠,且天然适配事件驱动场景(如 resize、scroll)。
- setTimeout 方案(如“防抖式节流”)实际是混合策略,不属于纯节流
- 纯节流强调“固定窗口内至多一次”,时间戳法最直接体现这一语义
- 浏览器事件循环中,时间戳对比发生在宏任务/微任务内,响应及时

















