跳到主要内容

防抖函数绑定 this

· 阅读需 2 分钟
Hanasaki
阿巴阿巴阿巴

为什么防抖这样写不行?

function debounce(fn, delay) {
let timeout;
return function () {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(fn, delay, ...arguments);
};
}

如果没用到 this,这样写确实没什么关系,但是如果在防抖的回调函数里用到了 this,那么它指向哪里呢?

答案是指向了全局环境。

实验代码

下面的代码,将输出 undefined,因为 this 指向了全局环境,this.aundefined

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 是从作用域链上继承下来的,而普通函数内部有自己的 thisarguments ,我们需要的拿闭包函数里的 thisarguments(做个“转发”)。

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);
};
}