防抖函数绑定 this
· 阅读需 2 分钟
为什么防抖这样写不行?
function debounce(fn, delay) {
let timeout;
return function () {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(fn, delay, ...arguments);
};
}
如果没用到 this
,这样写确实没什么关系,但是如果在防抖的回调函数里用到了 this
,那么它指向哪里呢?
答案是指向了全局环境。
实验代码
下面的代码,将输出 undefined
,因为 this
指向了全局环境,this.a
为 undefined
。
const obj = {
a: 1,
log: debounce(function () {
console.log(this.a);
}, 500)
};
obj.log(); // undefined
所以很多网上常见的写法,都有手动绑定 this
这一步,将返回的闭包函数的 this
绑定到回调函数上,这样就可以正常输出 a 的值了。
function debounce(fn, delay) {
let timeout;
return function () {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments); // 绑定 this 和 arguments 并执行
}, delay);
};
}
或者,也可以这样写,区别仅在于箭头函数的 this
是从作用域链上继承下来的,而普通函数内部有自己的 this
和 arguments
,我们需要的拿闭包函数里的 this
和 arguments
(做个“转发”)。
function debounce(fn, delay) {
let timeout;
return function () {
if (timeout) clearTimeout(timeout);
const context = this; // 拿到 this
const args = arguments; // 拿到 arguments
timeout = setTimeout(function () {
fn.apply(context, args); // 绑定 context 和 args 并执行
}, delay);
};
}