有人可以清楚地分解这里发生的事情吗?
function timerCheck() {
for(var i=0; i<5; i++) {
setTimeout(function() {
console.log("Hello" + i);
}, 3000);
}
}
所以你们中的一些人可能知道,调用此函数不会按预期工作。最终会发生的是,这个函数将被一次调用 5 次,每次我都设置为 5。这将是 3 秒后的输出:
Hello5
Hello5
Hello5
Hello5
Hello5
我也明白使用 setInterval 方法是解决此类问题的正确方法,但我很好奇这里的幕后情况。我真的很想了解 Javascript 是如何工作的。请注意,我没有计算机科学背景,只是一个自学成才的编码员。
最佳答案
这可能有助于您更好地了解发生了什么:
function timerCheck() {
for(var i=0; i<5; i++) {
console.log("Hi" + i);
setTimeout(function() {
console.log("Hello" + i);
}, 3000);
console.log("Bye" + i);
}
}
你会看到
Hi0
Bye0
Hi1
Bye1
Hi2
Bye2
Hi3
Bye3
Hi4
Bye4
立即打印到控制台,因为循环的所有五次迭代都很快完成,然后在五秒钟后您将看到:
Hello5
Hello5
Hello5
Hello5
Hello5
因为超时(几乎在同一时间设置)全部同时发生,并且由于循环已经完成:i == 5
.
这是由 i
的范围引起的.变量 i
在 timerCheck();
中声明后,范围为 everywhere在 setTimeout 设置的匿名函数中没有本地 i 没有 var i
, 和 i
不作为函数的参数给出。
您可以使用闭包轻松解决此问题,闭包将返回一个具有 i 的本地副本的函数:
function timerCheck() {
for(var i=0; i<5; i++) {
setTimeout((function(loc_i) {
return function() {
console.log("Hello" + loc_i);
};
})(i), 3000);
}
}
输出:
Hello0
Hello1
Hello2
Hello3
Hello4
要理解这一点:
(function(loc_i) {
return function() {
console.log("Hello" + loc_i);
};
})(i)
你必须知道在 Javascript 中一个函数是可以立即执行的。 IE。 (function(x){ console.log(x); })('Hi');
版画 Hi
到控制台。因此,上面的外部函数只接受一个参数(i
的当前值)并将其存储到该函数的一个局部变量中,称为 loc_i
。 .该函数立即返回一个打印 "Hello" + loc_i
的新函数到控制台。也就是传入超时的函数。
我希望一切都说得通,如果您对某些事情仍然不清楚,请告诉我。
关于javascript - 幕后发生了什么?循环中的 Javascript 计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8197249/