简而言之
首先,您的所有断言都是正确的。
- 第一个循环一直运行,直到它突然退出(使用中断、返回、抛出等)。
- 第二个循环运行直到它突然退出,但也执行变量赋值,并增加一个值。
- 第三个 for 循环像正常的 for 循环一样运行,直到中心条件为假。它的身体是空的。
但是为什么 JavaScript 会这样做呢?
让我们深入了解为什么会发生这种情况。
如果我们仔细查看语言规范,我们可以看到在 for 循环中发生了以下情况:
IterationStatement : for ( ExpressionNoIn(opt) ; Expression(opt) ; Expression(opt)) 语句
我将在其余答案中处理这些陈述和该定义。
现在让我们来看看这些案例。
如果for(;;)
发生以下情况之一:
ExpressionNoIn 不存在,因此该子句不需要调用任何内容(如第 1 条所述)。
第二个表达式不在,所以我们不返回调用(如第 3 条所述)。
第三个表达式为空,因此不执行“增量”(如第 3.f 条所述)。
所以它基本上会像你预测的那样无休止地重复(直到用 a 打破break
或返回,或抛出以及通常导致突然完成的任何事情)。(正如条款 e 和 d 告诉我们的那样)。
在第二种情况下for (var i = 0; ; ++i)
,会发生以下情况:
在第三种情况下for (var p; p; p = someValue) /* empty body */ ;
,会发生以下情况:
这评估为一个 for 循环。语句确实是空的,但 for 循环并不真正关心。唯一的区别是for 循环没有返回任何值。基本上它是一个完整且合法的 for 循环。;
只是一个空语句。当您想在实际循环中运行没有内容的 for 循环时,它很有用。您有时会在特征检测中看到这一点。当您想找到最小值时,这也很有用n
......
您是正确的,因为它会一直运行直到该值是错误的,或者更准确地调用ToBoolean
它会产生 false
. 正如第 3.a.ii 条规定的那样。
如您所见,这一切都在规范中并且定义明确:)
程序员为什么要这样做?
在第一个片段中,使用break
子句执行他们的流控制。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<=10;i++);
并得到第一个大于 10 的数字。