HTMLCollection 元素的 For 循环 [英] For loop for HTMLCollection elements

查看:24
本文介绍了HTMLCollection 元素的 For 循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置 HTMLCollectionOf 中所有元素的 get id.我写了以下代码:

var list = document.getElementsByClassName("events");控制台日志(列表[0].id);对于(列表中的键){控制台日志(key.id);}

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

event1不明确的

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

解决方案

针对最初的问题,您错误地使用了 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(让列表项){控制台.log(item.id);}

要包括旧版浏览器(包括 IE 之类的东西),这将适用于任何地方:

var list = document.getElementsByClassName("events");for (var i = 0; i < list.length; i++) {console.log(list[i].id);//第二个控制台输出}


为什么不应该使用for/in

的解释

for/in 用于迭代对象的属性.这意味着它将返回对象的所有可迭代属性.虽然它似乎适用于数组(返回数组元素或伪数组元素),但它也可以返回对象的其他属性,这些属性不是您对类数组元素所期望的.而且,你猜怎么着,HTMLCollectionnodeList 对象都可以有其他属性,这些属性将通过 for/in 迭代返回.我只是在 Chrome 中尝试过这个,并按照你迭代的方式迭代它会检索列表中的项目(索引 0、1、2 等...),但也会检索 lengthitem 属性.for/in 迭代根本不适用于 HTMLCollection.


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

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

<预><代码>012物品命名项@@迭代器长度

希望现在你能明白为什么要使用 for (var i = 0; i < list.length; i++) 代替,这样你就可以得到 0, 12 在您的迭代中.


浏览器支持 NodeList 和 HTMLCollection 迭代的演进

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

2015 年 ES6 更新

添加到 ES6 的是 Array.from() 它将把类似数组的结构转换为实际的数组.这允许像这样直接枚举列表:

严格使用";Array.from(document.getElementsByClassName("events")).forEach(function(item) {控制台.log(item.id);});

工作演示(截至 2016 年 4 月在 Firefox、Chrome 和 Edge 中):https://jsfiddle.net/jfriend00/8ar4xn2s/


2016 年 ES6 更新

您现在可以将 ES6 for/of 结构与 NodeListHTMLCollection 一起使用,只需将其添加到您的代码中即可:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

然后,你可以这样做:

var list = document.getElementsByClassName("events");for (var 列表项) {控制台.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(让列表项){控制台.log(item.id);}

工作演示(在 Chrome 和 Firefox 中):http://jsfiddle.net/jfriend00/3ddpz8sp/

2017 年 12 月针对 ES6 的第三次更新

截至 2017 年 12 月,此功能在 Edge 41.16299.15.0 中适用于 nodeList,如 document.querySelectorAll(),但不适用于 HTMLCollectiondocument.getElementsByClassName() 中的一样,因此您必须手动分配迭代器以在 Edge 中将其用于 HTMLCollection.为什么他们会修复一种集合类型,而不是另一种,这完全是个谜.但是,您现在至少可以在 Edge 的当前版本中使用带有 ES6 for/of 语法的 document.querySelectorAll() 的结果.

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

2018 年 3 月 ES6 的第四次更新

根据 mesqueeeb,Symbol.iterator 支持也已内置到 Safari 中,因此您可以将 for (let item of list) 用于任一 document.getElementsByClassName()document.querySelectorAll().

2018 年 4 月 ES6 第五次更新

显然,Edge 18 将于 2018 年秋季支持使用 for/of 迭代 HTMLCollection.

2018 年 11 月 ES6 第六次更新

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

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

I'm trying to set get id of all elements in an HTMLCollectionOf. I wrote the following code:

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

But I got the following output in console:

event1
undefined

which is not what I expected. Why is the second console output undefined but the first console output is event1?

In response to the original question, you are using for/in incorrectly. In your code, key is the index. So, to get the value from the pseudo-array, you'd have to do list[key] and to get the id, you'd do list[key].id. But, you should not be doing this with for/in in the first place.

Summary (added in Dec 2018)

Do not ever use for/in to iterate a nodeList or an HTMLCollection. The reasons to avoid it are described below.

All recent versions of modern browsers (Safari, Firefox, Chrome, Edge) all support for/of iteration on DOM lists such nodeList or HTMLCollection.

Here's an example:

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

To include older browsers (including things like IE), this will work everywhere:

var list = document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
    console.log(list[i].id); //second console output
}


Explanation For Why You Should Not Use for/in

for/in is meant for iterating the properties of an object. That means it will return all iterable properties of an object. While it may appear to work for an array (returning array elements or pseudo-array elements), it can also return other properties of the object that are not what you are expecting from the array-like elements. And, guess what, an HTMLCollection or nodeList object can both have other properties that will be returned with a for/in iteration. I just tried this in Chrome and iterating it the way you were iterating it will retrieve the items in the list (indexes 0, 1, 2, etc...), but also will retrieve the length and item properties. The for/in iteration simply won't work for an HTMLCollection.


See http://jsfiddle.net/jfriend00/FzZ2H/ for why you can't iterate an HTMLCollection with for/in.

In Firefox, your for/in iteration would return these items (all the iterable properties of the object):

0
1
2
item
namedItem
@@iterator
length

Hopefully, now you can see why you want to use for (var i = 0; i < list.length; i++) instead so you just get 0, 1 and 2 in your iteration.


Evolution of Browser Support for NodeList and HTMLCollection iteration

Following below is an evolution of how browsers have evolved through the time period 2015-2018 giving you additional ways to iterate. None of these are now needed in modern browsers since you can use the options described above.

Update for ES6 in 2015

Added to ES6 is Array.from() that will convert an array-like structure to an actual array. That allows one to enumerate a list directly like this:

"use strict";

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

Working demo (in Firefox, Chrome, and Edge as of April 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/


Update for ES6 in 2016

You can now use the ES6 for/of construct with a NodeList and an HTMLCollection by just adding this to your code:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

Then, you can do:

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

This works in the current version of Chrome, Firefox, and Edge. This works because it attaches the Array iterator to both the NodeList and HTMLCollection prototypes so that when for/of iterates them, it uses the Array iterator to iterate them.

Working demo: http://jsfiddle.net/jfriend00/joy06u4e/.


Second Update for ES6 in Dec 2016

As of Dec 2016, Symbol.iterator support has been built-in to Chrome v54 and Firefox v50 so the code below works by itself. It is not yet built-in for Edge.

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

Working demo (in Chrome and Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/

Third Update for ES6 in Dec 2017

As of Dec. 2017, this capability works in Edge 41.16299.15.0 for a nodeList as in document.querySelectorAll(), but not an HTMLCollection as in document.getElementsByClassName() so you have to manually assign the iterator to use it in Edge for an HTMLCollection. It is a total mystery why they'd fix one collection type, but not the other. But, you can at least use the result of document.querySelectorAll() with ES6 for/of syntax in current versions of Edge now.

I've also updated the above jsFiddle so it tests both HTMLCollection and nodeList separately and captures the output in the jsFiddle itself.

Fourth Update for ES6 in Mar 2018

Per mesqueeeb, Symbol.iterator support has been built-in to Safari too, so you can use for (let item of list) for either document.getElementsByClassName() or document.querySelectorAll().

Fifth Update for ES6 in Apr 2018

Apparently, support for iterating an HTMLCollection with for/of will be coming to Edge 18 in Fall 2018.

Sixth Update for ES6 in Nov 2018

I can confirm that with Microsoft Edge v18 (that is included in the Fall 2018 Windows Update), you can now iterate both an HTMLCollection and a NodeList with for/of in Edge.

So, now all modern browsers contain native support for for/of iteration of both the HTMLCollection and NodeList objects.

这篇关于HTMLCollection 元素的 For 循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆