遍历 JavaScript 对象数组时出现奇怪的行为?

29
var myArr = [{a:1, b:2}, {c:3, d:4}];

for (var item in myArr) {
    console.log(item);
}

为什么返回的是键(例如:0、1),而不是对象本身?

4个回答

36

JavaScript: The Good Parts中,Douglas Crockford建议避免使用for in语句。

如果您使用for in循环来遍历对象中的属性名称,则结果不是有序的

for in循环最适用于迭代名称-值对,而for each循环最适用于迭代值,即数组。

E.g,

var o = {'name':'Batman', 'age':33, 'city':'Gotham City'};
   for (var p in o) {
        console.log(p+': '+o[p]);
    }

如果我们使用上述对象的 For Each 循环,就无法获取属性名称。


注意:

  1. For in循环最适用于名称-值对。
  2. For Each循环最适用于可迭代的值。例如:数组和对象,如果您不关心属性的名称。

谢谢。我一直想读那本书。我不知道存在“for each”循环 - 这是所有主要浏览器都支持的吗? - Andy Hin
3
@Andy:for each ... in语句是仅在基于Mozilla的实现中可用的扩展(它在其他浏览器上无法运行)。当使用数组时,只需使用任何顺序循环即可...另请参阅 - Christian C. Salvadó
1
值得注意的是,for..in 对于稀疏数组非常有用,前提是处理继承的可枚举属性(例如hasOwnProperty测试),并且顺序不重要。 - RobG
2
这不应该被标记为答案,因为它适用于简单数组,而不是对象数组。 - Luke Pring
1
这个答案已经过时了。使用 ECMAScript 6 中的 for...of 循环是实现这个功能的新且大大改进的方法。请参见下面的答案。 - GrayedFox

22

Javascript 的 for..in 循环总是返回索引/名称,而不是值。要获取你想要的值,你应该使用:

var myArr = [{a:1, b:2}, {c:3, d:4}];

for (var index in myArr) {
    console.log( myArr[index] );
}

但是,如前所述,for .. in语句应该谨慎使用,并且不适用于数组。相反,你应该使用for循环。

var myArr = [{a:1, b:2}, {c:3, d:4}];

for( var i=0, l=myArr.length; i<l; i++ ) {
    console.log( myArr[i] );
}

3
for ... in 循环遍历对象的键(属性)。
它不适用于数组。
它还将遍历从对象的原型继承的属性。

1
但它不是一个哈希映射/键值对。如果我使用 ['a','b','c'] 或 [1,2,3] 进行 for...in 循环,它将返回值而不是索引。编辑:刚看到你的更新。那我就用普通的 for 循环迭代吧。谢谢! - Andy Hin
4
@andy: 错了,它会返回索引。数组只是具有数字键和特殊 length 属性的对象。 - SLaks

1

为了适应最新的ECMAScript 6标准,添加一个答案。

查看this页面,了解具有示例的精彩阅读。

还有一个相当美味的警告:这个惊人的新功能将与几乎所有可迭代对象一起工作!来自MDN:

for...of语句创建一个循环,遍历可迭代对象(包括数组、映射、集合、字符串、TypedArray、参数对象等)...

例如,你可以使用:

for (let item of myArr) {
    console.log(item);
} 

尽管很明显你正在记录一个对象,但为了让下一个读你代码的人更加友好,我建议将“item”改名为“obj”,如下所示:
for (let obj of myArr) {
    console.log(obj);
} 

为什么要重命名变量?虽然我们使用术语“item”来表示数组中的任何通用项,但您的数组仅包含对象。如果您知道或期望此数组仅包含对象,则可以根据数组包含的类型(即对象)来命名变量。
编码愉快!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接