什么';这是怎么回事?循环中的Javascript计时器
有人能把这里发生的事情说清楚吗什么';这是怎么回事?循环中的Javascript计时器,javascript,timer,settimeout,Javascript,Timer,Settimeout,有人能把这里发生的事情说清楚吗 function timerCheck() { for(var i=0; i<5; i++) { setTimeout(function() { console.log("Hello" + i); }, 3000); } } 我也知道使用setInterval方法是解决这类问题的正确方法,但我很好奇这里到底发生了什么。我真的很想了解Javascript是如何工作的。请注意,我没有计算机
function timerCheck() {
for(var i=0; i<5; i++) {
setTimeout(function() {
console.log("Hello" + i);
}, 3000);
}
}
我也知道使用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);
}
}
立即打印到控制台,因为循环的所有五次迭代都很快完成,五秒钟后,您将看到:
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);
}
}
要了解这一点:
(function(loc_i) {
return function() {
console.log("Hello" + loc_i);
};
})(i)
您必须知道,函数可以在Javascript中立即执行。例如,(函数(x){console.log(x);})('Hi')代码>将Hi
打印到控制台。因此,上面的外部函数只接收一个参数(当前值i
),并将其存储到名为locu i
的函数的局部变量中。该函数立即返回一个新函数,将“Hello”+loc_i
打印到控制台。这是传递到超时的函数
我希望这一切都有意义,如果您还不清楚什么,请告诉我。JavaScript中的变量范围仅限于函数
在您的示例中,变量i
在timerCheck
中声明。这意味着在循环结束时,i
将等于5
现在,添加对setTimeout
的调用不会改变这样一个事实,即i
的作用域是timerCheck
,并且在每个setTimeout
调用运行时,i
已修改为等于5
您可以创建一个函数来“捕获”i
的值,这样当您从循环内部调用它时,您就可以得到setTimeout
调用的新变量范围:
function createTimer(j) {
setTimeout(function() {
console.log("Hello" + j);
}, 3000);
}
function timerCheck() {
for(var i=0; i<5; i++) {
createTimer(i);
}
}
函数createTimer(j){
setTimeout(函数(){
console.log(“Hello”+j);
}, 3000);
}
函数timerCheck(){
对于(var i=0;i,这实际上是Andrews答案的一个附加部分
如果您试图设置一个设置输出的变量,它也会解释范围
function test()
{
for(var i=0; i<5; i++) {
t = "Hello " + i + "<br/>";
document.write(t);
setTimeout(function() {
document.write(t);
}, 3000);
}
}
从循环和
Hello 4
Hello 4
Hello 4
Hello 4
Hello 4
从setTimeout中,前面问题的可能重复要求一个解决方案。我正在寻找对实际发生的情况的彻底解释。因此,这不是它的重复。好的,让我看看我是否得到了这个。循环运行得非常快,几乎在同一时间调用setTimeout函数5次(因为循环运行得太快了)。因此,当您等待setTimeout函数执行时,i已经达到5。但是,您可以通过每次设置一个闭包来在本地存储i,但这仍然会同时运行,对吗?@Shaan是的,我想您明白了。尝试将console.log
更改为:console.log(“Local:“+loc_i+”,i:“+i);
。在第二个版本中,您将看到loc_i
和i
都在内部函数中定义。是的,我现在看到了。loc_i指向关闭环境,i指向函数计时器范围中设置的i。谢谢!
function createTimer(j) {
setTimeout(function() {
console.log("Hello" + j);
}, 3000);
}
function timerCheck() {
for(var i=0; i<5; i++) {
createTimer(i);
}
}
function test()
{
for(var i=0; i<5; i++) {
t = "Hello " + i + "<br/>";
document.write(t);
setTimeout(function() {
document.write(t);
}, 3000);
}
}
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
Hello 4
Hello 4
Hello 4
Hello 4
Hello 4