原因很简单。arr
使用以下代码创建数组:
var arr = new Array(10000);
所以它的长度为 10000,但所有元素都是undefined
. 此循环不适用于数组长度,但会在遇到“虚假”值时终止 - 假设由于尝试读取数组末尾而v
接收到值时循环将停止。undefined
但是在这个特定的数组中,所有一万个元素都有值undefined
。因此,循环在测试数组的第一个元素时停止。换句话说,它根本不循环!难怪它很快。
但是更真实的案例呢?这种循环如何处理冗长的 JSON 对象数组:
[
{ "id": 507674, "name": "Kolink" },
{ "id": 997356, "name": "DarkLord7854" },
{ "id": 1202830, "name": "Michael Geary" },
/* and thousands more */
]
在这里,您不会遇到循环立即终止的问题,因为数组元素都是“真实的”。
使用现代 JavaScript 引擎,这被证明是编写循环的一种相当糟糕的方式,因为我最近发现让我非常尴尬。
我是jQuery Cookbook的作者之一:我编写了第 5 章“更快、更简单、更有趣”的大部分内容。好吧,“更快”的部分并没有那么好。我推荐了一个非常像您的循环来迭代大量对象,例如上面的对象:
for( var item, i = -1; item = array[++i]; ) {
// do stuff with item
}
事实证明,在现代浏览器中,这比像这样的传统循环要慢得多:
for( var i = 0, n = array.length; i < n; i++ ) {
var item = array[i];
// do stuff with item
}
部分原因是因为试图读取数组末尾的内容会使一些 JavaScript 引擎重新回到未优化的数组表示方式中,正如 V8 作者之一在去年的 Google I/O 上向我解释的那样。部分原因可能是浏览器优化了更常见的循环类型,而不是优化了这种不太常见的方法。
无论哪种方式,更传统的循环在现代浏览器中变得更快:
http://jsperf.com/mikes-loops/2
但这与您的循环不同。在你的情况下,疯狂的性能提升直接是因为它根本不运行循环。:-)