我被告知不要使用。。。在JavaScript中使用数组。为什么不呢?


当前回答

除了。。。在所有可枚举财产的循环中(这与“所有数组元素”不同!),请参阅http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf,第12.6.4节(第5版)或13.7.5.15节(第7版):

列举财产的机制和顺序。。。未指定。。。

(强调我的。)

这意味着,如果浏览器愿意,它可以按照插入财产的顺序浏览这些属性。或按数字顺序排列。或者按照词法顺序(其中“30”在“4”之前!请记住,所有对象键——因此,所有数组索引——实际上都是字符串,所以这是完全有意义的)。如果它将对象实现为哈希表,那么它可以按桶遍历它们。或者把其中任何一个加上“向后”。浏览器甚至可以随机迭代,并且符合ECMA-262,只要它访问每个属性一次即可。

实际上,大多数浏览器目前都喜欢以大致相同的顺序进行迭代。但没有什么可以说他们必须这样做。这是特定于实现的,如果发现另一种方式更有效,随时可能会改变。

不管怎样,因为。。。它没有秩序的内涵。如果您关心顺序,请明确它,并使用带索引的正则for循环。

其他回答

除了其他答案中给出的原因外,如果需要计算计数器变量,您可能不想使用“for…In”结构,因为循环会迭代对象财产的名称,因此该变量是一个字符串。

例如

for (var i=0; i<a.length; i++) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

将写入

0, number, 1
1, number, 2
...

鉴于

for (var ii in a) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

将写入

0, string, 01
1, string, 11
...

当然,这可以通过包括

ii = parseInt(ii);

但第一种结构更直接。

因为它通过对象字段而不是索引枚举。你可以用索引“length”获得值,我怀疑你是否想要这个。

主要有两个原因:

One

就像其他人所说的那样,您可能会得到不在数组中或从原型继承的密钥。因此,假设库向Array或Object原型添加了一个属性:

Array.prototype.someProperty = true

您可以将其作为每个阵列的一部分:

for(var item in [1,2,3]){
  console.log(item) // will log 1,2,3 but also "someProperty"
}

可以使用hasOwnProperty方法解决此问题:

var ary = [1,2,3];
for(var item in ary){
   if(ary.hasOwnProperty(item)){
      console.log(item) // will log only 1,2,3
   }
}

但这对于使用for in循环迭代任何对象都是正确的。

Two

通常,数组中项目的顺序很重要,但for in循环不一定以正确的顺序迭代,这是因为它将数组视为对象,这是在JS中实现的方式,而不是数组。这看起来是一件小事,但它确实会破坏应用程序,而且很难调试。

这不一定是坏的(根据您正在做的事情),但在数组的情况下,如果在Array.prototype中添加了一些东西,那么您将得到奇怪的结果。您希望此循环运行三次:

var arr = ['a','b','c'];
for (var key in arr) { ... }

如果一个名为helpfulUtilityMethod的函数被添加到Array的原型中,那么循环将运行四次:键将是0、1、2和helpfulUtilityMethod。如果你只需要整数,噢。

A代表。。。in循环总是枚举键。对象财产键始终是String,甚至是数组的索引财产:

var myArray = ['a', 'b', 'c', 'd'];
var total = 0
for (elem in myArray) {
  total += elem
}
console.log(total); // 00123