当前位置: 首页 > 面试题库 >

HTMLCollection元素的For循环

鄢开诚
2023-03-14
问题内容

我试图设置获取所有元素的ID HTMLCollectionOf。我写了以下代码:

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

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

event1
undefined

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


问题答案:

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

摘要

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

所有最新版本的现代浏览器(Safari,Firefox,Chrome,Edge)都支持for/ofDOM列表(例如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等…),但还将检索lengthitem属性。该for/in迭代根本不会对的HTMLCollection工作。

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

0
1
2
item
namedItem
@@iterator
length

我们希望,现在你可以看到为什么要使用for(vari=0;i<list.length;i++)代替你只是得到012在你的迭代。

以下是浏览器在2015-2018年期间的演变方式的演变,为您提供了其他迭代方式。由于您可以使用上述选项,因此在现代浏览器中现在不需要这些了。

2015年ES6更新

ES6中增加了Array.from()将类似数组的结构转换为实际数组的功能。这样就可以像这样直接枚举列表:

"use strict";

Array.from(document.getElementsByClassName("events")).forEach(function(item) {
   console.log(item.id);
});

2016年ES6更新

您现在可以使用ES6与构建物/ 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中有效。之所以可行,是因为它将Array迭代器同时附加到NodeList和HTMLCollection原型,以便当进行for/ of迭代时,它使用Array迭代器对其进行迭代。

ES6的第二次更新于2016年12月

截至2016年12月,Symbol.iteratorChromev54和Firefoxv50已内置支持,因此以下代码可独立运行。Edge尚未内置。

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

ES6的第三次更新(2017年12月)

截至2017年12月,此功能在Edge41.16299.15.0中适用nodeList于indocument.querySelectorAll()而不是HTMLCollectioninin,document.getElementsByClassName()因此您必须手动分配迭代器才能在Edge中将其用于HTMLCollection。为什么要修复一种收集类型而不是另一种收集类型,这完全是个谜。但是,现在至少可以在当前版本的Edge中使用document.querySelectorAll()带有ES6for/of语法的结果。

我还更新了上述的jsfiddle所以它同时测试HTMLCollectionnodeList分开,并捕获的的jsfiddle本身的输出。

ES6的第四次更新于2018年3月

每mesqueeeb,Symbol.iterator支持已经内置Safari浏览器,所以你可以使用for(letitemoflist)的两种document.getElementsByClassName()document.querySelectorAll()

ES6的第五次更新于2018年4月

显然,对HTMLCollectionwith 进行迭代的支持for/of将在2018年秋季提供给Edge 18。

ES6的第六次更新于2018年11月

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

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



 类似资料:
  • 问题内容: Javascript中的“ for…in”循环是否按声明的顺序遍历哈希表/元素?有没有按顺序执行的浏览器? 我希望使用的对象将被声明 一次, 并且永远不会被修改。 假设我有: 我进一步将它们用于: 我是否可以期望在大多数体面的浏览器中,“ A:“ Hello””总是排在“ B:“ World””之前? 问题答案: 当前,所有主流浏览器都按照定义它们的顺序遍历对象的属性。Chrome可以

  • 我是C#的新手,我正在尝试制作一个程序来提示用户输入关于8个vocalist.genre输入的信息,然后根据vocalist.genre输入的内容将这些信息分类到文本文件中。但是,当我尝试使用for循环来处理用户的输入时,我遇到了一个问题。我该怎么办? }

  • 我有这个代码: outlets是传递给方法的ArrayList;riverBasin是int(int[]riverBasin)的2D“矩阵”; 从ArrayList outlets中删除“项”会生成错误: 但我并不完全理解。然而,我怀疑我弄坏了迭代器。对的那么我如何删除ArrayList中不需要的元素呢。 提前感谢您的帮助, 里卡多

  • 问题内容: 我有一个整数列表,我正在运行-loop来发现两个元素的总和是否等于另一个变量。所以,如果是等于和我有一个整数列表: ,那么函数应该打印所有数字的不同组合,。 我感觉自己快到了,但是当我使用该功能时,列表中发生了一些奇怪的事情。下面的代码用于显示所有需要计算的数字组合,但是列表中的所有其他元素都被跳过。 这是输出: 请注意如何,,,和被跳过。我正在使用第二个-loop不会使用原始值,然后

  • 问题内容: 我有一个清单 我想在如下所示的for循环中删除此列表中的元素: 但这是行不通的。我能做什么? 问题答案: 使用循环遍历列表时,不允许从列表中删除元素。 重写代码的最佳方法取决于你要执行的操作。 例如,你的代码等效于: 另外,你可以使用while循环: 我正在尝试删除符合条件的项目。然后我转到下一个项目。 你可以将每个不符合条件的元素复制到第二个列表中: 或者,你可以使用filter或列

  • 问题内容: 我有这种方法,可以在登录前检查用户名和密码。现在,我的for循环仅检查第一个项目,它发现第一个项目不满足第一个条件,因此与其去检查第二个项目,它只是中断并返回null。 为什么会这样? 这是我的方法: 问题答案: 因此,请尝试此代码。