防抖和节流均封装为返回新函数的高阶函数,通过闭包维护定时器ID或时间戳;防抖支持immediate选项与.cancel(),节流推荐时间戳版并提供.flush()和.cancel();均正确透传this与参数。

防抖和节流封装成通用高阶函数,核心是返回一个新函数,内部用闭包维护状态(如定时器 ID 或时间戳),并根据策略决定是否执行原函数。两者都应支持手动取消,且参数清晰、行为可预测。
防抖函数:最后一次触发后延时执行
适用于输入搜索、窗口 resize 等场景,目标是“等用户停下来再干活”。关键点:
- 每次调用都清除旧定时器,重设新定时器
- 支持 immediate 选项:为 true 时首次触发立即执行,后续进入等待期
- 返回函数自带 .cancel() 方法,用于主动中止待执行逻辑
示例实现:
function debounce(fn, delay, options = {}) {
const { immediate = false } = options;
let timerId = null;
<p>const debounced = function (...args) {
if (timerId !== null) {
clearTimeout(timerId);
}
if (immediate && timerId === null) {
fn.apply(this, args);
}
timerId = setTimeout(() => {
if (!immediate) {
fn.apply(this, args);
}
timerId = null;
}, delay);
};</p><p>debounced.cancel = function () {
if (timerId !== null) {
clearTimeout(timerId);
timerId = null;
}
};</p><p>return debounced;
}节流函数:固定间隔内最多执行一次
适用于 scroll、mousemove 等连续高频事件,目标是“匀速干活,不卡顿”。推荐使用时间戳版,更精准可靠:
立即学习“Java免费学习笔记(深入)”;
- 记录上一次执行时间,当前触发时对比是否超过 delay
- 提供 .flush() 方法:立即执行一次并重置计时起点
- 提供 .cancel() 方法:清空上次记录的时间戳(便于重用)
示例实现:
function throttle(fn, delay) {
let lastTime = 0;
<p>const throttled = function (...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};</p><p>throttled.flush = function () {
fn.apply(this, arguments);
lastTime = Date.now();
};</p><p>throttled.cancel = function () {
lastTime = 0;
};</p><p>return throttled;
}使用时注意 this 和参数传递
所有封装都用 ...args 和 fn.apply(this, args),确保原函数的上下文和实参正确透传。避免直接写 fn(...args),否则 this 会丢失(尤其在事件监听器中)。
小程序或模块化环境中的导出方式
在微信小程序等环境中,可统一导出为工具模块:
// utils/performance.js
export { debounce, throttle };或 CommonJS 方式:
module.exports = { debounce, throttle };然后在页面中按需引入调用,例如:formSubmit: util.debounce(handleSubmit, 1000)。


















