Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这是怎么回事?循环中的Javascript计时器_Javascript_Timer_Settimeout - Fatal编程技术网

什么';这是怎么回事?循环中的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