小编典典

HTMLCollection 元素的 for 循环

all

我正在尝试设置HTMLCollectionOf. 我写了以下代码:

var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
    console.log(key.id);
}

但是我在控制台中得到了以下输出:

event1
undefined

这不是我所期望的。为什么第二个控制台输出undefined是第一个控制台输出event1


阅读 202

收藏
2022-03-08

共1个答案

小编典典

在回答原始问题时,您使用for/in不正确。在您的代码中,key是索引。所以,要从伪数组中获取值,你必须这样做list[key],而要获取
id,你必须这样做list[key].id。但是,你不应该首先这样做for/in

摘要(2018 年 12 月添加)

永远不要for/in用于迭代 nodeList 或 HTMLCollection。避免它的原因如下所述。

所有最新版本的现代浏览器(Safari、Firefox、Chrome、Edge)都支持for/of在 DOM
列表上迭代,例如nodeListHTMLCollection.

这是一个例子:

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用于迭代对象的属性。这意味着它将返回对象的所有可迭代属性。虽然它可能看起来适用于数组(返回数组元素或伪数组元素),但它也可以返回对象的其他属性,这些属性不是您对类似数组元素的期望。而且,你猜怎么着,一个HTMLCollectionnodeList对象都可以有其他属性,这些属性将随着for/in迭代返回。我刚刚在
Chrome 中尝试过,并按照您迭代的方式对其进行迭代,它将检索列表中的项目(索引 0、1、2
等…),但也会检索lengthitem属性。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,12


浏览器支持 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 结构和 aNodeList和 an 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.iteratorChrome 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 中适用于nodeListas in
document.querySelectorAll(),但不适用于HTMLCollectionas in
document.getElementsByClassName()因此您必须手动分配迭代器才能在 Edge 中为HTMLCollection.
为什么他们会修复一种集合类型,而不是另一种,这完全是个谜。但是,您现在至少可以在当前版本的 Edge
中使用document.querySelectorAll()with ES6语法的结果。for/of

我还更新了上面的 jsFiddle,因此它分别测试HTMLCollectionnodeList在 jsFiddle 本身中捕获输出。

2018 年 3 月 ES6 的第四次更新

根据 mesqueeeb,Symbol.iteratorSafari 也内置了支持,因此您可以使用for (let item of list)或.document.getElementsByClassName()``document.querySelectorAll()

2018 年 4 月 ES6 的第五次更新

显然, 2018 年秋季 Edge 18 将支持迭代HTMLCollectionwith 。for/of

2018 年 11 月 ES6 的第六次更新

我可以确认,使用 Microsoft Edge v18(包含在 2018 年秋季 Windows 更新中),您现在可以在 Edge 中使用 for/of
迭代 HTMLCollection 和 NodeList。

for/of因此,现在所有现代浏览器都包含对 HTMLCollection 和 NodeList 对象迭代的原生支持。

2022-03-08