例如
//防抖(非立即执行)
function debounce(fn, delay = 500) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
timer = null
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay)
}
}
这个fn绑定this执行的意义何在? 求解
###假如你在使用 Vue
,其中的一个 method
需要防抖,那么最简洁的写法是这样:
{
methods: {
click: debounce(function(){
// ↑上面的 function 就是防抖函数里的 fn,但是 fn 实际上
// 是由防抖函数里的 function 调用的,调用的时候如果不给
// 它绑定 this,下面这句代码就不能用 this 访问 Vue 实例
this.counter ++;
})
}
}
而如果 debounce
函数不提供 this
的绑定,同样的功能可能得这样写:
{
methods: {
// 为了夸大对比效果我特意用了 IIFE
// 实际上可以把 handler 放到外面,
// 以避免使用 IIFE
click: (() => {
let args = null;
const handler = debounce(fn => fn(...args));
return function(...realArgs){
args = [...realArgs];
handler(() => {
this.counter++;
});
}
})()
}
}
###因为如果不绑定 this,会出现典型的 this 丢失的情况。
从这个 debounce
的代码看,它的功能是通过传入一个 fn,得到这个 fn 的延迟执行版本,方便后续调用。
所以,可以假设一下用例:
let test = { name: 'testThis' };
test.debounceFn = debounce(function () {
console.log("for test: ", this.name);
});
test.debounceFn();
如果用 apply 绑定了 this,运行结果是: for test: testThis
。
如果未绑定,运行结果是:for test: undefined
。
这是因为 test.debounceFn() 的 this 指向是这个 test 对象。但是 debounceFn 方法中的 fn 方法,作为参数传入 setTimeout 后,是独立运行的,this 指向丢失。
这里是通过 test.debounceFn -> 箭头函数 -> fn.apply 一步步把 test 对象作为 this 值绑定给了 fn。