防抖是“等停再干”,节流是“定时定量干”;防抖适合操作有明确结束点的场景,节流适合持续发生且需保底响应的场景;二者核心在于触发时机与适用场景的理解和参数调试。

直接从核心逻辑入手,不绕弯子——防抖和节流本质都是“控频”,但控法不同:防抖是“等停再干”,节流是“定时定量干”。掌握它们,关键不在背代码,而在理解触发时机、识别适用场景、能动手调参落地。
先搞清触发逻辑,别被术语卡住
防抖就像电梯关门:你按一次按钮,它开始倒计时 5 秒;第 3 秒你又按了一次,倒计时重置回 5 秒;只有你连续 5 秒没按,门才关、动作才执行。所以它适合“用户操作有明确结束点”的场景。
节流像公交发车:不管上车人多密集,每 10 分钟准时发一班车。你刚上完一辆,下一班要等满 10 分钟才来。所以它适合“持续发生、必须保底响应”的场景。
一句话区分:防抖只认最后一次,节流只认固定间隔。
从手写基础版开始,理解闭包和定时器协作
不建议直接抄 Lodash 源码。先写两个极简版本,重点体会变量如何在闭包中“存住状态”:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 防抖:用
let timer = null记住上次的定时器 ID,每次触发先clearTimeout(timer),再timer = setTimeout(...) - 节流(时间戳版):用
let lastTime = 0记住上次执行时间,每次触发算Date.now() - lastTime,够间隔才执行并更新lastTime
写完后自己改参数测试:把防抖 delay 设成 10ms,快速输入 5 个字,看控制台只打 1 次;把节流 delay 设成 1000ms,疯狂滚动页面,看日志是否基本每秒 1 条。
进阶不是加功能,而是懂取舍
真实项目里,你常会遇到这些选择题:
- 搜索框要不要“立即执行第一下”?比如用户输第一个字就查拼音首字母,后面再防抖——那就得支持
immediate参数的防抖 - 滚动监听要不要保证“停止时也触发一次”?比如滚动到底部加载更多,停那一刻必须检查——那就不能只靠时间戳,得结合
setTimeout做尾调用 - 按钮防重复提交,该用防抖还是节流?答案是:都行,但防抖更自然(用户点完就等响应,不再点);节流则更适合“允许每 2 秒点一次”的弱限制场景
这时候别硬套模板,打开浏览器开发者工具,在 console 里实时改函数参数、观察 performance 面板的帧率变化,比看十篇教程都管用。
练熟三个高频实战组合
真正用得多的不是单技术,而是搭配:
-
输入搜索 + 防抖 + 取消上一个请求:用
AbortController配合防抖,避免用户连输时旧请求还在跑 -
滚动监听 + 节流 + IntersectionObserver:节流控制位置计算频率,用
IntersectionObserver替代getBoundingClientRect判断元素是否进入视口,性能翻倍 -
窗口缩放 + 防抖 + CSS 自适应:先用防抖等用户调完窗再重排布局,同时优先用
rem、vw、@media减少 JS 干预
每个组合做一遍小 demo,部署到 GitHub Pages,用手机真机测一测触摸延迟,你就知道哪一步拖了后腿。










