js 装饰器实现防抖
使用装饰器实现防抖
防抖(Debounce)是一种常见的技术,用于限制函数在短时间内频繁触发。通过装饰器(Decorator)可以优雅地实现这一功能。
基础防抖装饰器
function debounce(delay) {
let timeoutId;
return function(target, key, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
originalMethod.apply(this, args);
}, delay);
};
return descriptor;
};
}
使用方式:
class MyClass {
@debounce(300)
handleInput() {
console.log('Input handled after debounce');
}
}
立即执行版本
有时需要首次调用立即执行,后续调用才进行防抖:
function debounceImmediate(delay) {
let timeoutId;
let shouldCall = true;
return function(target, key, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
if (shouldCall) {
originalMethod.apply(this, args);
shouldCall = false;
}
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
shouldCall = true;
}, delay);
};
return descriptor;
};
}
带取消功能的防抖
function debounceWithCancel(delay) {
let timeoutId;
return function(target, key, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
originalMethod.apply(this, args);
}, delay);
};
// 添加取消方法
descriptor.value.cancel = function() {
clearTimeout(timeoutId);
};
return descriptor;
};
}
使用方式:
const instance = new MyClass();
instance.handleInput(); // 正常调用
instance.handleInput.cancel(); // 取消待执行的调用
TypeScript 版本
对于 TypeScript 项目,可以添加类型声明:

function debounceTS(delay: number) {
let timeoutId: ReturnType<typeof setTimeout>;
return function(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
originalMethod.apply(this, args);
}, delay);
};
return descriptor;
};
}
注意事项
- 装饰器目前是 ECMAScript 的提案,需要使用 Babel 插件
@babel/plugin-proposal-decorators进行转译 - 在类方法中使用时,
this绑定是正确的 - 防抖时间应根据实际场景调整,通常 200-500ms 适用于用户输入场景
- 多次快速调用时,只有最后一次调用会实际执行






