FOR 循环 htmlCollection 元素

2022-08-29 22:42:29

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

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

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

event1
undefined

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


答案 1

在回答原始问题时,您使用了错误。在代码中,是索引。因此,要从伪数组中获取值,您必须执行并获取id,您将执行。但是,您首先不应该这样做。for/inkeylist[key]list[key].idfor/in

摘要(2018 年 12 月添加)

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

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

下面是一个示例:

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用于迭代对象的属性。这意味着它将返回对象的所有可迭代属性。虽然它可能看起来适用于数组(返回数组元素或伪数组元素),但它也可以返回对象的其他属性,这些属性不是您期望从类似数组的元素中获得的。而且,猜猜看,一个 或 对象都可以具有其他属性,这些属性将与迭代一起返回。我刚刚在Chrome中尝试了一下,并以迭代的方式迭代它将检索列表中的项目(索引0,1,2等),但也将检索和属性。迭代根本不适用于 HTMLCollection。HTMLCollectionnodeListfor/inlengthitemfor/in


请参阅 http://jsfiddle.net/jfriend00/FzZ2H/,了解为什么不能使用 来迭代 HTMLCollection。for/in

在 Firefox 中,您的迭代将返回以下项(对象的所有可迭代属性):for/in

0
1
2
item
namedItem
@@iterator
length

希望现在你可以看到为什么你想使用,所以你只是得到,并在你的迭代中。for (var i = 0; i < list.length; i++)012


浏览器对 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 构造与 a 和 a 一起使用,只需将其添加到代码中即可:NodeListHTMLCollection

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。这是有效的,因为它将数组迭代器附加到 NodeList 和 HTMLCollection 原型,以便在 for/of 迭代它们时,它使用数组迭代器来迭代它们。

工作演示:http://jsfiddle.net/jfriend00/joy06u4e/


2016 年 12 月 ES6 的第二次更新

截至 2016 年 12 月,Chrome v54 和 Firefox v50 内置了对它的支持,因此下面的代码可以独立工作。它尚未内置于 Edge 中。Symbol.iterator

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

我还更新了上面的jsFiddle,因此它可以单独测试两者,并在jsFiddle本身中捕获输出。HTMLCollectionnodeList

2018年3月ES6第四次更新

根据 mesqueeeb,Safari 也内置了对 Safari 的支持,因此您可以将其用于 或 。Symbol.iteratorfor (let item of list)document.getElementsByClassName()document.querySelectorAll()

2018年4月ES6第五次更新

显然,对迭代的支持将在2018年秋季进入Edge 18。HTMLCollectionfor/of

2018年11月ES6第六次更新

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

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


答案 2

您不能在 s 或 s 上使用 / 。但是,您可以使用某些方法,只要将它们传入或作为 .forinNodeListHTMLCollectionArray.prototype.call()NodeListHTMLCollectionthis

因此,请考虑以下作为 jfriend00 的 for 循环的替代方案:

var list= document.getElementsByClassName("events");
[].forEach.call(list, function(el) {
    console.log(el.id);
});

关于MDN有一篇很好的文章涵盖了这种技术。请注意他们关于浏览器兼容性的警告:

[...]将主机对象(如 a )传递给本机方法(如 )并不能保证在所有浏览器中都有效,并且已知在某些浏览器中会失败。NodeListthisforEach

因此,虽然这种方法很方便,但循环可能是与浏览器最兼容的解决方案。for

更新(2014 年 8 月 30 日):最终,您将能够使用ES6 for/of

var list = document.getElementsByClassName("events");
for (const el of list)
  console.log(el.id);

它已在最新版本的Chrome和Firefox中得到支持。