防抖函数的基本实现
下面是一种常见的防抖函数写法:
const debounce = (fn, delay) => {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
为什么需要 clearTimeout(timer)?
一个常见误解。设置 timer = null 并不会取消定时器,真正取消的是 clearTimeout(timer) 。
如果不手动清除,之前的定时器依然会在延迟后执行,造成不必要的多次调用。
this 丢失问题示例
有些防抖函数实现中,调用回调时省略了 apply 或 call,直接使用了:
fn(...args)
这看起来简洁,但可能会导致 this 上下文丢失,在某些情况下引发 bug。
具体例子
const obj = {
name: "Alice",
sayName() {
console.log("我的名字是", this.name);
}
};
我们给 sayName 方法添加防抖:
const debounce1 = (func, delay) => {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func(...args); // ❌ 没有绑定 this
}, delay);
};
};
obj.sayNameDebounced = debounce1(obj.sayName, 500);
obj.sayNameDebounced();
预期输出
我的名字是 Alice
实际输出
我的名字是 undefined
原因分析
当我们执行 func(...args) 时,并没有指定 this,
因此 sayName 中的 this 默认为 undefined(严格模式下)或 window(非严格模式下),而不是 obj。
如何修复
使用 apply(this, args),显式传递 this: