在javascript中混淆for循环输出

时间:2017-01-18 10:24:04

标签: javascript for-loop

我正在读你不懂JS书系列。

在范围&的第5章中。这本书的关闭标题,这个for循环我无法理解

for (var i=1; i<=5; i++) {
setTimeout( function timer(){
    console.log( i );
}, i*1000 );}

在1秒间隔后,它在控制台中打印6次。 甚至作者也试图解释为什么会发生这种情况,但我无法得到他想说的话。

您可以在此处找到此代码的解释: https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md

前往&循环+关闭&#39;您将在页面上找到此代码。

任何人都可以用简单的语言解释我吗? 为什么它在控制台中打印6次5次而不是1次,2次,...,5秒后间隔。

先谢谢你的时间和时间。努力。

6 个答案:

答案 0 :(得分:3)

是的,因为循环在第二个循环中运行,那时i的值是6(,最后一个i ++没有进入循环)。因此它使用  该值要渲染5次。

您可以使用以下内容打印1,2,3,4,5

for (let  i=1; i<=5; i++) {
setTimeout( function timer(){
    console.log( i );
}, i*1000 );}

使用let定义i的范围,该范围是ES6

的一部分

答案 1 :(得分:1)

这种情况发生是因为SetTimeoutFunction中还有另一个范围。

如果您使用ES6,您可以看到1 2 3 4 5。

for (let i=1; i<=5; i++) {
  setTimeout( function timer(){
    console.log( i );
  }, i*1000 );
}

这里使用let创建特殊变量,可以在SetTimeout范围内使用。

答案 2 :(得分:1)

这里存在简单逻辑。第一次进入循环并调用定时器功能。但定时器功能将等待1秒钟。在这1秒内,for循环将执行所有6次,最后是i = 6中的值。

和计时器功能也会在一秒内执行6次。

在定时器仅执行第一次之前i = 6中的值。 同样地,这个我的值也是接下来的5倍。

如果您只想更改代码,请按照以下方式

  for (var i=1; i<=11; i++) {
    setTimeout( function timer(){
    console.log( i );
   }, i*1000 );}

然后它打印11次10次

答案 3 :(得分:0)

循环在您启动后立即运行,并将6的值增加到i。 setTimeout中的回调函数在此之后运行1到5秒,并打印6的实际值,始终为6,因为循环在第0秒将其设置为library(dplyr) library(plm) data(Cigar) model_plm <- plm(price ~ sales, index = c("state"), model = "within", data = Cigar) summary(model_plm) C <- cbind(seq(100,150,10)) pred <- expand.grid(sales = C) pred$fixef <- mean(fixef(model_plm)) pred$b_sales <- coef(summary(model_plm))[1] pred$yhat <- with(pred, sales*b_sales + fixef) pred$yhat_se <- sqrt((diag(C%*%vcov(model_plm)%*%t(C)))) pred <- mutate(pred, lwr=yhat-1.96*yhat_se, upr=yhat+1.96*yhat_se) pred 。 / p>

答案 4 :(得分:0)

因为i是在setTimeout执行的函数的上下文之外定义的,所以当达到超时时,i的值为6,因此所有超时都将执行该函数并打印i的当前值。

正如你所说,章节的标题是Closures,你可以使用闭包来解决这个问题。

for (var i=1; i<=5; i++) {

 //This is a IIFE (Immediately-invoked function expression)
 //Simply put, a function that will be executed right after its definition
 (function(curr) {
   setTimeout( function timer(){
     console.log( curr );
   }, i*1000 );}
 })(i)

}

在上面的示例中,curr变量包含在该上下文中,并将保存调用函数时使用的值。

答案 5 :(得分:0)

让我一步一步解释:

for (let  i=1; i<=5; i++) {
setTimeout( function timer(){
    console.log( i );
}, i*1000 );}

第一次迭代:

我是1,  第一个计时器设置为1 * 1000 = 1秒

第二次迭代:

我是2岁,  第二个计时器设置为2 * 1000 = 2秒

第3次迭代:

我是3岁,  第3个定时器设置为3 * 1000 = 3秒

第4次迭代:

我是4岁,  第4个定时器设置为4 * 1000 = 4秒

第5次迭代:

我是5岁,  第5个定时器设置为5 * 1000 = 5秒

当我变为6时,它退出循环,所以现在我们有5个定时器,时间分别为1,2,3,4和5秒,i的当前值为6.所有定时器都已设置但没有执行因为1秒还没有过去。

1秒后,第1个计时器结束,打印6个 2秒后,第二个计时器结束,打印6个 等等....

因此你得到一个输出:66666,每个间隔为1秒,但实际的计时器值是1,2,3,4和5秒

相关问题