在回答原始问题时,您错误地使用了for/in。在您的代码中,key 是索引。因此,要从伪数组中获取值,您必须执行 list[key] 并获取 id,您必须执行 list[key].id。但是,您首先不应该使用 for/in 来执行此操作。
摘要(2018 年 12 月添加)
永远不要使用for/in 来迭代nodeList 或HTMLCollection。避免它的原因如下所述。
所有最新版本的现代浏览器(Safari、Firefox、Chrome、Edge)都支持 for/of 在 DOM 列表上迭代,例如 nodeList 或 HTMLCollection。
这是一个例子:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
要包括旧版浏览器(包括 IE 之类的东西),这将适用于任何地方:
var list = document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
为什么不应该使用for/in的解释
for/in 用于迭代对象的属性。这意味着它将返回对象的所有可迭代属性。虽然它可能看起来适用于数组(返回数组元素或伪数组元素),但它也可以返回对象的其他属性,这些属性不是您对类似数组元素的期望。而且,你猜怎么着,HTMLCollection 或nodeList 对象都可以具有其他属性,这些属性将通过for/in 迭代返回。我刚刚在 Chrome 中尝试过,并按照您迭代的方式对其进行迭代,它将检索列表中的项目(索引 0、1、2 等...),但也会检索 length 和 item 属性。 for/in 迭代根本不适用于 HTMLCollection。
请参阅 http://jsfiddle.net/jfriend00/FzZ2H/,了解为什么不能使用 for/in 迭代 HTMLCollection。
在 Firefox 中,您的 for/in 迭代将返回这些项目(对象的所有可迭代属性):
0
1
2
item
namedItem
@@iterator
length
希望现在您能明白为什么要使用for (var i = 0; i < list.length; i++),这样您就可以在迭代中获得0、1 和2。
浏览器支持 NodeList 和 HTMLCollection 迭代的演变
以下是浏览器在 2015 年至 2018 年期间如何演变的演变,为您提供了更多迭代方式。由于您可以使用上述选项,因此现代浏览器现在不需要这些。
2015 年 ES6 更新
添加到 ES6 的是Array.from(),它将一个类似数组的结构转换为一个实际的数组。这允许人们像这样直接枚举一个列表:
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
工作演示(截至 2016 年 4 月在 Firefox、Chrome 和 Edge 中):https://jsfiddle.net/jfriend00/8ar4xn2s/
2016 年 ES6 更新
您现在可以将 ES6 for/of 结构与 NodeList 和 HTMLCollection 添加到您的代码中:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
那么,你可以这样做:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
这适用于当前版本的 Chrome、Firefox 和 Edge。这是可行的,因为它将 Array 迭代器附加到 NodeList 和 HTMLCollection 原型上,因此当 for/of 迭代它们时,它使用 Array 迭代器来迭代它们。
工作演示:http://jsfiddle.net/jfriend00/joy06u4e/。
2016 年 12 月 ES6 的第二次更新
截至 2016 年 12 月,Symbol.iterator 支持已内置于 Chrome v54 和 Firefox v50,因此以下代码可自行运行。它还没有内置在 Edge 中。
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
工作演示(在 Chrome 和 Firefox 中):http://jsfiddle.net/jfriend00/3ddpz8sp/
2017 年 12 月 ES6 的第三次更新
截至 2017 年 12 月,此功能在 Edge 41.16299.15.0 中适用于 nodeList,如 document.querySelectorAll(),但不适用于 HTMLCollection,如 document.getElementsByClassName(),因此您必须手动分配迭代器才能使用它在 Edge 中获取 HTMLCollection。为什么他们会修复一种集合类型,而不是另一种,这完全是个谜。但是,您现在至少可以在当前版本的 Edge 中使用 document.querySelectorAll() 和 ES6 for/of 语法的结果。
我还更新了上面的 jsFiddle,因此它分别测试 HTMLCollection 和 nodeList 并在 jsFiddle 本身中捕获输出。
2018 年 3 月 ES6 的第四次更新
对于 mesqueeeb,Safari 也内置了Symbol.iterator 支持,因此您可以将for (let item of list) 用于document.getElementsByClassName() 或document.querySelectorAll()。
2018 年 4 月 ES6 的第五次更新
显然,2018 年秋季 Edge 18 将支持使用 for/of 迭代 HTMLCollection。
2018 年 11 月 ES6 的第六次更新
我可以确认,使用 Microsoft Edge v18(包含在 2018 年秋季 Windows 更新中),您现在可以在 Edge 中使用 for/of 迭代 HTMLCollection 和 NodeList。
所以,现在所有现代浏览器都包含对 HTMLCollection 和 NodeList 对象的 for/of 迭代的原生支持。