在回答原始问题时,您使用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
ornodeList
对象都可以有其他属性,这些属性将通过for/in
迭代返回。我只是在 Chrome 中尝试过这个,并按照您迭代的方式进行迭代,它将检索列表中的项目(索引 0、1、2 等...),但也会检索length
和item
属性。该for/in
迭代根本不会对的HTMLCollection工作。
请参阅http://jsfiddle.net/jfriend00/FzZ2H/了解为什么您不能使用for/in
.
在 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 更新
您现在可以通过将以下内容添加到您的代码中来使用带有 aNodeList
和 an的 ES6 for/of 构造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 中适用于 a nodeList
as in document.querySelectorAll()
,但不适用于HTMLCollection
as in,document.getElementsByClassName()
因此您必须手动分配迭代器以在 Edge 中为HTMLCollection
. 为什么他们会修复一种集合类型,而不是另一种,这完全是个谜。但是,您现在至少可以在Edge 的当前版本中document.querySelectorAll()
使用 ES6for/of
语法的结果。
我还更新了上述的jsfiddle所以它同时测试HTMLCollection
和nodeList
分开,并捕获的的jsfiddle本身的输出。
2018 年 3 月 ES6 的第四次更新
根据 mesqueeeb,Symbol.iterator
Safari 也内置了支持,因此您可以将其for (let item of list)
用于document.getElementsByClassName()
或document.querySelectorAll()
.
2018 年 4 月 ES6 第五次更新
显然,Edge 18 将在 2018 年秋季支持迭代HTMLCollection
with for/of
。
2018 年 11 月 ES6 的第六次更新
我可以确认,使用 Microsoft Edge v18(包含在 2018 年秋季 Windows 更新中),您现在可以在 Edge 中使用 for/of 迭代 HTMLCollection 和 NodeList。
因此,现在所有现代浏览器都包含for/of
对 HTMLCollection 和 NodeList 对象迭代的本机支持。