javascript中什么是防抖和节流_它们如何提升性能【教程】
技术百科
夢幻星辰
发布时间:2026-01-28
浏览: 次 防抖与节流是事件响应策略:防抖只执行最后一次触发(如搜索框停顿后请求),节流则按固定间隔执行(如滚动中每200ms检查位置),二者均用于避免高频无意义调用,而非直接优化CPU或内存性能。
防抖和节流不是“性能优化技巧”,而是「事件响应策略」
它们不直接提升 CPU 或内存性能,而是防止函数被高频、无意义地调用——比如用户狂输 10 个字,input 事件触发 10 次,你却发了 10 次搜索请求;或者拖拽窗口时 resize 每毫秒触发几十次,你却反复重算 DOM 尺寸。真正拖慢页面的,是这些本可跳过的逻辑执行,而非事件本身。
防抖:debounce(fn, delay) —— 只信“最后一击”
每次触发都清掉旧定时器,只在停止触发 delay 毫秒后执行一次。适合“结果比过程重要”的场景:
- 搜索框联想:用户打完 “react” 停顿 300ms 后才查,中间删改都不发请求
- 表单校验(邮箱格式):输入中不提示,光标移出或停顿时再验
- 按钮防重复提交:点击后立刻禁用 + 防抖,避免双击触发两次 API
⚠️ 容易踩的坑:
-
debounce返回的是新函数,不能在addEventListener里每次写debounce(handleInput, 300),否则每次渲染都新建闭包,clearTimeout失效 → 必须提前定义并复用:const debouncedInput = debounce(handleInput, 300) - 没传
this和参数:原始事件回调里的this是 DOM 元素,但防抖函数里会丢失 → 必须用fn.apply(this, arguments)或展开参数 -
delay设太小(如 50ms)≈ 没防抖;设太大(如 800ms)用户会明显感知延迟 → 搜索建议推荐 200–300ms,表单校验可设 400–500ms
节流:throttle(fn, interval) —— 要“节奏感”,不要“全漏掉”
保证

interval 毫秒执行一次,不管触发多密。适合“需要感知过程但不能太密”的交互:
-
scroll监听吸顶或懒加载:滚动中每 200ms 检查一次 scrollTop,既不卡顿也不错过关键位置 - 鼠标拖拽更新坐标:canvas 绘图、自定义 slider,不需要每帧都算,16ms(60fps)或 50ms 更合理
-
mousemove实时预览:避免鼠标划过时疯狂重绘缩略图
⚠️ 容易踩的坑:
- 时间戳版(推荐)首次立即执行,但若需“首次也等间隔”,得用定时器版(带
leading/trailing控制) - 别把
interval设成 0 或负数 —— 会导致无限循环或不执行 - 在 Vue/React 中,别在
render或useEffect里动态生成节流函数,同样会破坏引用稳定性 → 应提至组件外或用useCallback缓存
选错就等于交互逻辑错:防抖 vs 节流,本质是业务语义问题
不是“哪个更快”,而是“你要响应什么”:
- 用户 resize 窗口:用防抖 —— 等他拖完再重排布局,稳
- 用户 scroll 页面想实时显示“已滚动高度百分比”:用节流 —— 防抖会卡住不动,直到他停手,体验断层
- 游戏里按空格射击:用节流(
interval=200ms)限制射速,不是防抖 —— 防抖会让连按变单发,节流才能实现“每 200ms 最多一发”的节奏
真实项目中,lodash 的 _.debounce 和 _.throttle 已处理取消、立即执行、this 绑定等边界,比手写更可靠;但前提是理解它们为何这样设计 —— 否则连配置项都看不懂,比如 leading: true 是啥意思,maxWait 解决什么问题。
# ai
# 的是
# 也不
# 表单
# 首次
# 而非
# 性能优化
# app
# 鼠标
# 拖拽
# input
# 循环
# javascript
# java
# 事件
# this
# 联想
# 闭包
# dom
# canva
# const
# 懒加载
# 邮箱
# 重绘
# react
# vue
# canvas
# 无意义
# 你却
# 防抖
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- PHP cURL GET请求:正确设置认证与自定义
- 如何用正则表达式精确匹配“start”到“end”
- Win11摄像头无法使用怎么办_Win11相机隐私
- ACF 教程:如何正确更新嵌套在多层 Group
- Win11怎么设置屏保时间_调整Win11屏幕保护
- 如何使用Golang table-driven f
- Win11怎么关闭贴靠布局_Win11禁用窗口最大
- Win11怎么设置快速访问主页_Windows11
- PythonPandas数据分析项目教程_时间序列
- Windows怎样拦截WPS弹窗广告_Window
- 如何将竖排文本文件转换为横排字符串
- Windows10如何更改鼠标灵敏度_Win10鼠
- 如何使用Golang sync.Map实现并发安全
- Win11怎么把图标拖到任务栏_Win11固定应用
- Win10怎么设置开机密码_Windows10账户
- 如何处理“XML格式不正确”错误 常见XML we
- Python数据抓取合法性_合规说明【指导】
- c++如何用AFL++进行模糊测试 c++ Fuz
- Windows10系统更新错误0x80070002
- 如何减少Golang内存碎片化_Golang内存分
- php订单日志怎么按状态筛选_php筛选不同状态订
- php增删改查报错1054怎么办_字段名错误排查修
- Win11怎么设置多显示器任务栏 Win11扩展任
- Win10怎么关闭自动更新错误弹窗_Win10策略
- Python数据挖掘核心算法实践_聚类分类与特征工
- c++如何使用std::bitset进行位图算法_
- 如何使用Golang recover捕获panic
- Win11怎样安装企业微信_Win11安装企业微信
- Windows系统时间服务错误_W32Time服务
- Win11怎么卸载Photos应用_Win11卸载
- Win11怎么设置右键刷新选项_Windows11
- Django密码修改后会话失效的解决方案
- Win11如何设置电源计划_Win11电源计划优化
- C++友元类使用场景_C++类间协作设计方式讲解
- Windows11怎么用“记事本”自动换行与编码
- Windows10系统怎么查看显卡驱动_Win10
- 如何使用Golang管理模块版本_Golanggo
- Windows10如何更改桌面背景_Win10个性
- Windows 11如何开启文件夹加密(EFS)_
- 如何开启Windows的远程服务器管理工具(RSA
- VSC怎么创建PHP项目_从零开始搭建项目的步骤【
- 手机php怎么转mp4_手机端php文件转mp4a
- Win11怎么更改账户头像_Windows 11自
- Win11怎么解压RAR文件 Win11自带解压功
- 如何使用Golang读取日志文件_Golang b
- Win11怎么关闭专注助手 Win11关闭免打扰模
- php485返回空数组怎么回事_php485数据接
- Win11屏幕亮度突然变暗怎么解决_自动变暗问题处
- 如何使用Golang指针与结构体结合_修改结构体内
- Windows10系统怎么查看设备管理器_Win1

QQ客服