【发布时间】:2015-04-16 02:52:59
【问题描述】:
在 Codepen 中,我正在使用的特定 for 循环的确切执行顺序让我有些困惑。看看这两个循环,它们都做同样的事情:
var a = ['orange','apple'];
for (var i=0; i<2;i++) {
alert(a[i]);
}
for (var j=0, fruit; fruit = a[j++];) {
alert(fruit);
}
你可以在这里看到这个:http://codepen.io/nickbarry/pen/MYNzLP/
第一个循环是标准的、普通的 for 循环编写方式。正如预期的那样,它会提示“orange”,然后是“apple”。
我使用 MDN 的建议编写了第二个循环(在此处搜索“idiom”:https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript)。
它有效,但我不太明白为什么。我对 for 循环的理解,这在某些方面显然是不正确的(不止一种方式?)是: * for 循环在第一次运行之前评估第二个表达式的真实性。所以似乎当 for 循环评估第二个表达式的真实性时,它应该在设置 fruit 的值之前增加 j。所以第一次通过循环,水果应该等于“苹果”。 * 并且循环应该只运行一次,因为在第一次通过之后,当它再次评估第二个表达式以查看它是否仍然为真时,它应该再次增加 j 之前它返回一个值给fruit,因为没有值在索引位置 2,它应该返回一个错误的结果,并退出循环。
我不明白到底发生了什么。在计算第二个表达式之前,for 循环是否运行一次?但这似乎是不可能的,因为如果发生这种情况,警报将不会在第一次发出任何警报,因为水果还没有价值。
另外,MDN 文章的作者似乎喜欢第二种编写循环的方式——有什么理由更好吗?我猜它使用的字符更少,这很好。跳过 for 循环中的第三个表达式是否可以节省大量时间?还是只是“它很酷,因为它很聪明”之类的东西?
【问题讨论】:
-
它起作用的原因是它是一个后增量,而不是一个前增量。如果是
++j而不是j++,您的假设将是正确的。 -
如果你的目标是制造敌人,那么第二种编写循环的方式非常好。没有真正的好处,它更难阅读,如果数组中有错误的值,它会过早停止并且它可能更慢(尽管需要测试来确定)。
-
请注意,MDN 是一个 wiki。任何傻瓜都可以添加内容。同一篇文章实际上建议
for-in用于数组,但没有完整解释可能遇到的所有问题。 -
我想指出一个for循环是有效的,只要它具有以下结构
for(; ; ){}。 JS 不在乎这些分号之间的内容,但它们必须存在。您的循环不起作用,因为您正在尝试使用无效的索引 -1。循环在第一次迭代本身失败并且不会继续。 -
如果您真的想知道应该如何评估
for,请查看规范:ecma-international.org/ecma-262/5.1/#sec-12.6.3。
标签: javascript loops for-loop