setTimeout 以奇怪的方式使用闭包上下文
setTimeout use closure context in strange way
我有一个 debounce
函数,例如 var debounced = debounce(my_func, delay);
debounce
函数确保:
- 延迟期间
my_func
只能执行一次
my_func
不会早于 delay
毫秒 被调用
这里是:
var debounce = function(fn, delay) {
var scheduled;
return function() {
var that = this; // save context
console.log('this = ' + that);
if (!scheduled) {
scheduled = true;
setTimeout(function() {
scheduled = false;
//PROBLEM: `that` variable is always the same as on the first function call
console.log('executing... \nthis = ' + that);
fn.apply(that); //call function in saved context
}, delay);
}
}
}
测试:
var ctx;
var debounced = debounce(function() {
ctx = this;
}, 10);
debounced.call(11);
debounced.call(22); // PROBLEM: it leads to function invoked with this == 11 instead of this == 22
打印到控制台
"this = 11"
"this = 22"
"executing...
this = 11" // INSTEAD OF "this = 22"
您可以尝试类似的方法:
var debounce = function(fn, delay) {
var that = {};
var scheduled, last_fn;
return function() {
that.a = this;
console.log('this = ' + that.a);
if (!scheduled) {
scheduled = true;
setTimeout(function() {
scheduled = false;
console.log('executing... \nthis = ' + that.a);
fn.apply(that);
}, delay);
}
};
};
当您第一次调用 debounced.call(11)
时 that == 11
在调用上下文中 !scheduled == true
在此上下文中设置超时
下一个调用 debounced.call(22)
将 22 存储为本次调用上下文中的值,这与调用 setTimeout
的那个不同。
正如 Doron 指出的那样,解决方案是将变量存储在 debounced
返回函数的上下文之外。
我有一个 debounce
函数,例如 var debounced = debounce(my_func, delay);
debounce
函数确保:
- 延迟期间
my_func
只能执行一次 my_func
不会早于delay
毫秒 被调用
这里是:
var debounce = function(fn, delay) {
var scheduled;
return function() {
var that = this; // save context
console.log('this = ' + that);
if (!scheduled) {
scheduled = true;
setTimeout(function() {
scheduled = false;
//PROBLEM: `that` variable is always the same as on the first function call
console.log('executing... \nthis = ' + that);
fn.apply(that); //call function in saved context
}, delay);
}
}
}
测试:
var ctx;
var debounced = debounce(function() {
ctx = this;
}, 10);
debounced.call(11);
debounced.call(22); // PROBLEM: it leads to function invoked with this == 11 instead of this == 22
打印到控制台
"this = 11"
"this = 22"
"executing...
this = 11" // INSTEAD OF "this = 22"
您可以尝试类似的方法:
var debounce = function(fn, delay) {
var that = {};
var scheduled, last_fn;
return function() {
that.a = this;
console.log('this = ' + that.a);
if (!scheduled) {
scheduled = true;
setTimeout(function() {
scheduled = false;
console.log('executing... \nthis = ' + that.a);
fn.apply(that);
}, delay);
}
};
};
当您第一次调用 debounced.call(11)
时 that == 11
在调用上下文中 !scheduled == true
在此上下文中设置超时
下一个调用 debounced.call(22)
将 22 存储为本次调用上下文中的值,这与调用 setTimeout
的那个不同。
正如 Doron 指出的那样,解决方案是将变量存储在 debounced
返回函数的上下文之外。