debounce是防抖,等操作停止后执行最后一次;throttle是节流,按固定间隔最多执行一次。前者适用于搜索、表单校验等需响应最终结果的场景,后者适用于滚动、拖拽等需持续匀速反馈的场景。

Lodash 的 debounce 和 throttle 都是用来控制函数执行频率的工具函数,但适用场景和行为逻辑不同:debounce 是“等你停手再执行”,throttle 是“固定节奏执行”。用对了能显著提升性能,比如搜索框输入、窗口 resize、滚动监听等。
debounce:防抖——等操作完全停止后再执行一次
适合用户连续触发、只需响应最终结果的场景(如输入搜索、表单校验)。它会忽略中间调用,只在最后一次调用后等待指定延迟时间,若期间有新调用,则重新计时。
基本用法:
const debouncedSearch = _.debounce((query) => {console.log('发起搜索:', query);
}, 300);
// 绑定到输入事件
input.addEventListener('input', (e) => {
debouncedSearch(e.target.value);
});
关键点:
- 默认只在延迟结束后执行最后一次调用(leading: false, trailing: true)
- 想让第一次触发立刻执行,加
{ leading: true, trailing: false } - 想手动取消待执行的任务,调用
debouncedSearch.cancel() - 想立即执行并清空后续排队,用
debouncedSearch.flush()
throttle:节流——按固定间隔最多执行一次
适合需要持续反馈但又不能太频繁的场景(如滚动加载、鼠标拖拽、canvas 动画)。它保证函数在指定时间间隔内最多执行一次,其余调用会被忽略或延迟到下一个周期。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
基本用法:
const throttledHandleScroll = _.throttle(() => {console.log('滚动位置:', window.scrollY);
}, 100);
window.addEventListener('scroll', throttledHandleScroll);
关键点:
- 默认采用“首次触发立即执行,之后每间隔时间执行一次”(leading: true, trailing: true)
- 可配置
{ leading: false }让第一次也等间隔后才执行 - 支持
trailing: false关闭结尾补发(避免最后一次延迟执行) - 同样支持
.cancel()和.flush()方法
不依赖 Lodash 的轻量替代方案
如果项目没引入 Lodash,也可以手写简易版(适用于简单需求):
// debounce 简易实现function debounce(func, wait) {
let timeout;
return function executedFunction() {
const later = () => { func.apply(this, arguments); };
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// throttle 简易实现(时间戳版)
function throttle(func, limit) {
let inThrottle;
return function() {
if (!inThrottle) {
func.apply(this, arguments);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
选哪个?看场景需求
判断依据很直接:
- 要等用户“做完一件事”再响应 → 用 debounce(比如输入完搜、按钮连点只提交一次)
- 要“持续但匀速”地响应 → 用 throttle(比如滚动中实时更新吸顶状态、拖拽中持续计算位置)
- 不确定?先用 debounce,多数 UI 交互更友好;性能敏感且需稳定节奏时换 throttle










