更好地理解JavaScript for循环

时间:2013-08-05 13:27:48

标签: javascript for-loop

在从JS编辑器(Tern)中读取代码时,我遇到了for循环的各种用法,如下面的代码段所示:

代码段1 @ lines 463-468

for (;;) {
  /* some code */
}

代码段2 @ lines 97-100

for (var i = 0; ; ++i) {
  /* some code */
}

在同一个音符上,我也遇到了一个带有空体的for循环,例如:

for (var p; p; p = someValue) /* empty body */ ;

我想了解代码执行流程中会发生什么。

我的看法是,对于代码片段1,for循环没有条件,所以它可能会无休止地继续?对于代码段2中的代码,i会不断增加而不受限制?对于第三个循环,循环继续,直到为p分配了一个评估为false的东西?

这些是我脑子里的想法,但我不确定。请协助。

2 个答案:

答案 0 :(得分:5)

简而言之

首先,你的所有断言都是正确的。

  • 第一个循环一直运行,直到它突然退出(中断,返回,抛出等等。)。
  • 第二个循环一直运行,直到它突然退出,但也执行变量赋值,并递增一个值。
  • 第三个for循环像正常for循环一样运行,直到中心条件为假。它的身体是空的。

但是为什么JavaScript会这样做?

让我们深入研究为什么会发生这种情况。

如果我们仔细看看the language specification,我们可以看到以下内容发生在for循环中:

  

IterationStatement:for(ExpressionNoIn(opt); Expression(opt); Expression(opt))Statement

我会将这些陈述和该定义视为答案的其余部分。

现在让我们来看看案例。

如果for(;;)之一发生以下情况:

  • ExpressionNoIn不存在,因此没有为该子句调用任何内容(As子句1指出)。

  • 第二个表达式不在,所以我们不返回调用(如第3条所述)。

  • 第三个表达式为空,因此不会执行“增量”(如第3.f条所述)。

所以它基本上会像你预测的那样无休止地重复(直到从break中断,或从...返回,或从中抛出,并且通常是导致突然完成的任何东西)。 (正如条款e和d告诉我们的那样)。

在第二种情况for (var i = 0; ; ++i)中,会发生以下情况:

  • ExpressionNoIn存在,因此我们对其进行评估,并为其赋值get(如第1条所述)。我们不指定它。

  • 然后我们无休止地重复,因为第二个表达不在这里。所以我们继续,直到abrubt执行发生或发生中断。更具体地说,这是here

  • 我们在每次迭代时递增i,因为条款f表示。

在第三种情况for (var p; p; p = someValue) /* empty body */ ;中发生以下情况:

这评估为for循环。语句确实是空的,但for循环并不真正关心。唯一的区别是for循环中没有值返回。基本上它是一个完整且合法的循环。 ;只是一个空话。当您想要在实际循环中运行没有内容的for循环时,它非常有用。你有时会在特征检测中看到这一点。当您想要找到......

的最小n时,这也很有用

你是正确的,因为它会运行,直到值为false,或更准确calling ToBoolean on it produces false。如第3.a.ii条规定。

正如您所看到的,这一切都在规范中并且定义明确:)


编码员为什么要这样做?

在第一个代码段中,使用a break clause执行其流量控制。 if (eol >= pos || eol < 0) break;(他们检查行尾,这可以在更传统的for循环中完成)。

在第二个片段中,他们使用break进行流量控制:

 if (!definitions.hasOwnProperty(uniq)) { name = uniq; break; }

他们再次把它放在for循环中的break语句中。

第三个代码段不在上下文中,但是我们想要(通常的例子)找到大于10的第一个数字(或第10个div元素,或者是字符串的出现 - 你得到的)这个想法)。我们可以这样做:

for(var i = 0; i&lt; = 10; i ++);

获得第一个大于10的数字。

答案 1 :(得分:1)

你的理解是正确的。

第一个片段是无限循环;没有终止条件,所以循环(本身)将永远继续。这几乎肯定伴随着身体内某处的break语句,它将在运行时退出循环。 (另一种选择是抛出异常退出循环,尽管使用异常作为控制流是不好的做法。)当退出条件过于复杂而无法表达时,通常会出现此模式(或等效的while (true) {...})循环语句。

第二个片段类似于第一个片段,因为没有终止条件,它将永远运行。这还需要break语句(或异常)来终止循环。这里唯一的区别是计数器变量也在每次迭代时递增。

第三个片段是一个没有主体的循环,尽管测试和变量更新发生在循环的每次迭代中。如您所料,这一直持续到p评估为false。这个for循环完全等同于while循环版本:

var p;
while (p) {
    p = someValue;
}

可能会更清楚地说明分配在!p之前重复发生。