1. 节流(稀释操作)
规定在⼀个周期内,事件最多触发⼀次。如果事件在周期内再次触发,则忽略。
作用
在事件持续触发时,保证固定时间间隔内只执行一次。
常见场景:
滚动事件(scroll)、按钮点击防重复提交等。
常⻅实现思路:
当前时间 - 上次触发的时间 >= delay
使⽤⼀个时间戳记录上次触发的时间
,判断当前触发距离上次触发的时间间隔是否⼤于等于指定的周期。 节流(Throttle)和防抖(Debounce)是控制函数执行频率的两种常用技术,它们有各自清晰的适用场景。
js
// 节流函数
function throttle(fn, delay = 300) {
let last = 0
return function (...args) {
const context = this
const now = Date.now()
if (now - last >= delay) {
fn.apply(context, args)
last = now
}
}
}
2.防抖(多次操作合并成最后一次)
在事件频繁触发时,只在最后一次触发后等待一段时间再执行。
常⻅实现思路
使⽤ setTimeout 设置⼀个定时器,如果事件在定时器到期前再次触发,则清除之前的定时器,并重新设置⼀个新的定时器。
常见场景
搜索框输入联想 (停止输入后再请求),表单验证(输入完成后再校验)
js
// 防抖函数
function debounce(fn, delay = 300) {
let timer = null
return function (...args) {
const context = this
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context, args)
timer = null
}, delay)
}
}
立即执行的防抖
js
function advancedDebounce(fn, delay, immediate = false) {
let timer = null;
const debounced = function(...args) {
const context = this;
if (timer) clearTimeout(timer);
if (immediate) {
const callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
if (callNow) fn.apply(context, args);
} else {
timer = setTimeout(() => {
fn.apply(context, args);
timer = null
}, delay);
}
};
// 添加取消方法
debounced.cancel = function() {
if (timer) {
clearTimeout(timer);
timer = null;
}
};
return debounced;
}
📊 核心区别一览
对比维度 | 节流 (Throttle) | 防抖 (Debounce) |
---|---|---|
核心思想 | 固定时间间隔内只执行一次,稀释执行频率。 | 连续触发时,只在最后一次触发后等待一段时间才执行,合并多次操作。 |
生活类比 | 像机关枪扫射,无论扣动扳机多快,子弹都按固定频率发射。 | 像电梯关门,有人进入后等待几秒关门,若期间有人进入则重新等待。 |
执行时机 | 固定间隔执行,保证在单位时间内至少执行一次。 | 延迟执行,只在连续触发停止后执行一次。 |
关键区别 | 关注过程的均匀性,不会丢失中间事件。 | 关注结果的唯一性,可能丢弃中间过程,只保留最终状态。 |
典型场景 | - 滚动事件 (如无限加载) - 鼠标移动 (如元素拖拽、Canvas绘图) - 窗口调整(resize) (需持续反馈布局时) - 按钮高频点击(如防止重复提交) | - 搜索框输入联想 (停止输入后再请求) - 表单验证 (输入完成后再校验) - 窗口调整(resize)(调整结束后再计算布局) |