支持取消操作的防抖函数需返回含run和cancel方法的对象,闭包中用let timer = null保存定时器id,每次run前清除旧定时器并重设,cancel方法清空timer,run中用func.apply(this, args)透传上下文与参数。

支持取消操作的防抖函数,核心是把定时器引用暴露在闭包中,让外部能随时清除它。关键不是只返回执行函数,而是返回一个对象,包含触发方法和取消方法。
闭包保存 timer 引用
防抖依赖 setTimeout,必须把它的返回值(timer ID)存在闭包变量里,后续才能调用 clearTimeout。不能每次调用都新建闭包,要确保多次调用共享同一个 timer 变量。
- 用
let timer = null声明在闭包顶层 - 每次触发前先
clearTimeout(timer) - 再重新赋值
timer = setTimeout(...)
返回带 cancel 方法的对象
只返回一个函数不够——无法主动取消。应返回形如 { run, cancel } 的对象,让调用方按需控制。
-
run是带防抖逻辑的执行函数(可接受参数) -
cancel内部调用clearTimeout(timer)并重置 timer - 取消后再次调用
run会重新开始计时
处理 this 和参数透传
实际使用常需保持原始调用上下文和参数。用 func.apply(thisArg, args) 而非直接调用 func()。
- 在
run中捕获this和arguments(或用 rest 参数) - 延迟执行时用
func.apply(context, args)确保正确绑定 - 若不关心 this,也可用箭头函数 + 展开语法:
() => func(...args)
完整示例代码
以下是一个生产可用的实现:
function debounce(func, delay) {
let timer = null;
return {
run(...args) {
const context = this;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
},
cancel() {
clearTimeout(timer);
timer = null;
}
};
}
// 使用方式:
const debouncedSearch = debounce(api.search, 300);
debouncedSearch.run('hello'); // 触发
debouncedSearch.cancel(); // 立即取消,不会发送请求











