JavaScript 防抖与节流:定义与核心应用场景
防抖和节流是 JavaScript 中用于控制高频事件触发频率的两种核心优化方案,目的是减少不必要的函数执行,提升页面性能和用户体验,二者在实现逻辑和适用场景上有本质区别。
一、防抖(Debounce)
1. 核心定义
防抖的核心逻辑是:触发高频事件后,函数不会立即执行,而是等待一段指定时间(延迟时间)后再执行;若在这段时间内事件再次被触发,则重新计时,只有当事件停止触发且超过延迟时间,函数才会执行一次。
可以通俗理解为:“等最后一次触发后,再冷静一会儿才执行”,类似电梯关门(有人进电梯就重新计时,没人进了才关门)。
2. 简单实现(非立即执行版)
javascript
运行
function debounce(fn, delay = 300) {
let timer = null; // 保存定时器标识
return function(...args) {
// 每次触发事件,清除之前的定时器,重新计时
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args); // 执行目标函数
}, delay);
};
}
3. 核心应用场景
防抖适用于「事件触发频繁,但只需执行最后一次结果」的场景:
- 搜索框输入联想:用户连续输入关键词时,无需每次输入都请求接口,等待用户停止输入(如 300ms 内无新输入)后,再触发搜索接口请求,减少无效请求;
- 窗口大小调整(resize) :用户拖拽窗口改变大小时,会高频触发
resize事件,用防抖只在用户停止拖拽后,执行一次页面布局调整逻辑; - 滚动条滚动到底部检测:无需滚动过程中频繁检测,等待滚动停止后再判断是否到达底部;
- 按钮防重复点击:如提交订单按钮,防止用户快速连续点击导致重复提交,防抖可确保只有最后一次点击(或点击后延迟)触发提交逻辑;
- 输入框实时校验(非即时) :如手机号、邮箱格式校验,等待用户输入完成后再校验,避免输入过程中频繁提示错误。
二、节流(Throttle)
1. 核心定义
节流的核心逻辑是:高频事件触发时,限制函数在指定时间间隔内只能执行一次,无论事件触发多少次,都会按照固定频率执行函数。
可以通俗理解为:“固定时间内,只执行一次”,类似水龙头滴水(无论怎么开关,每隔一段时间只滴一滴水)。
2. 简单实现(时间戳版)
javascript
运行
function throttle(fn, interval = 500) {
let lastTime = 0; // 记录上一次函数执行时间
return function(...args) {
const nowTime = Date.now(); // 获取当前时间
// 若当前时间与上一次执行时间的差值超过间隔,才执行函数
if (nowTime - lastTime >= interval) {
fn.apply(this, args);
lastTime = nowTime; // 更新上一次执行时间
}
};
}
3. 核心应用场景
节流适用于「事件触发频繁,且需要按固定频率执行函数」的场景:
- 滚动条滚动监听(如加载更多) :用户滚动页面时,无需每次滚动都触发加载逻辑,设置每隔 500ms 检测一次滚动位置,判断是否需要加载更多数据;
- 鼠标移动 / 拖拽事件(mousemove/drag) :如拖拽元素时,频繁触发
mousemove事件,用节流固定频率更新元素位置,避免页面卡顿; - 高频点击按钮(如点赞、刷新) :限制用户点赞频率(如 1 秒内只能点赞 1 次),防止恶意刷赞;
- 视频 / 音频播放进度更新:无需实时更新进度条,每隔 200ms 更新一次即可,减少 DOM 操作;
- 窗口滚动时的导航栏吸顶 / 吸底:滚动过程中按固定频率判断滚动距离,触发导航栏样式切换,避免频繁操作 DOM。
三、防抖与节流的核心区别
| 特性 | 防抖(Debounce) | 节流(Throttle) |
|---|---|---|
| 核心逻辑 | 等待最后一次触发后,延迟执行一次 | 固定时间间隔内,只执行一次 |
| 执行时机 | 事件停止触发后(延迟结束) | 事件触发过程中(按固定频率) |
| 触发频率 | 取决于事件停止触发的时间,可能很久执行一次 | 固定频率执行,不受事件触发频率影响 |
| 核心目的 | 过滤无效触发,保留最后一次结果 | 控制执行频率,避免过度执行 |
| 通俗比喻 | 电梯关门(有人进就重新计时) | 水龙头滴水(固定时间滴一滴) |
四、总结
- 防抖:“最后一次触发后延迟执行”,适合「只需最终结果」的场景(搜索联想、按钮防重复点击);
- 节流:“固定频率执行”,适合「需要持续反馈」的场景(滚动加载、鼠标拖拽);
- 二者本质都是减少高频事件的函数执行次数,提升页面性能,实际开发中可直接使用
lodash库的_.debounce()和_.throttle()(成熟稳定,支持更多配置)。