我试图在HTMLCollectionOf中设置所有元素的获取id。我写了下面的代码:

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

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

event1
undefined

这和我预料的不一样为什么第二个控制台输出是未定义的,而第一个控制台输出是event1?


当前回答

如果你使用ES的旧版本(例如ES5),你可以使用as any:

for (let element of elementsToIterate as any) {
      console.log(element);
}

其他回答

你想把它改成

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

在ES6中,你可以这样做[…]或者Array.from(collection),

let someCollection = document.querySelectorAll(someSelector)
[...someCollection].forEach(someFn) 
//or
Array.from(collection).forEach(someFn)

Eg:-

    navDoms = document.getElementsByClassName('nav-container');
    Array.from(navDoms).forEach(function(navDom){
     //implement function operations
    });

你也可以这样做:

 let elements = document.getElementsByClassName("classname");
 for(let index in  elements) {
   if(index <= elements.length) {
        console.log(elements[index]);
  }
}

let elements = document.getElementsByClassName("classname"); For (let index in elements) { If (index <= elements.length) { console.log(元素(指数)); } } <div class="classname"> element 1 </div> . <div class="classname"> element 2 </div> . <div class="classname"> element 3 </div> .

or

 let elements = document.getElementsByClassName("classname");
 for(let ele of  elements) {
        console.log(ele);
}

let elements = document.getElementsByClassName("classname"); For (let ele of elements) { console.log(避署); } <div class="classname"> element 1 </div> . <div class="classname"> element 2 </div> . <div class="classname"> element 3 </div> . <div class="classname"> element 4 </div> .

回答原来的问题,你用错了for/ In。在代码中,key是索引。因此,要从伪数组中获取值,你必须使用list[key],而要获取id,你必须使用list[key].id。但是,你一开始就不应该用for/in这样做。

摘要(2018年12月新增)

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

所有最新版本的现代浏览器(Safari, Firefox, Chrome, Edge)都支持DOM列表(如nodeList或HTMLCollection)上的/of迭代。

这里有一个例子:

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 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.


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

在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更新

你现在可以使用ES6 for/of构造一个NodeList和一个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/。


第二次更新ES6在2016年12月

截至2016年12月,Symbol。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中适用于document.querySelectorAll()中的nodeList,但不适用于document.getElementsByClassName()中的HTMLCollection,因此您必须手动分配迭代器以在Edge中使用HTMLCollection。为什么他们会修复一种收集类型,而不是另一种,这完全是一个谜。但是,你至少可以在Edge的当前版本中使用document.querySelectorAll()的结果与ES6 for/of语法。

我还更新了上面的jsFiddle,以便它分别测试HTMLCollection和nodeList,并在jsFiddle本身中捕获输出。

2018年3月ES6第四次更新

Per mesqueeeb,符号。Safari也内置了迭代器支持,所以你可以对document.getElementsByClassName()或document.querySelectorAll()使用for (let item of list)。

第五次更新ES6在2018年4月

显然,使用for/of迭代HTMLCollection的支持将在2018年秋季登陆Edge 18。

2018年11月ES6第六次更新

我可以确认,在Microsoft Edge v18(包括在2018年秋季Windows更新中),你现在可以在Edge中迭代一个HTMLCollection和一个NodeList。

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

在边缘

if(!NodeList.prototype.forEach) {
  NodeList.prototype.forEach = function(fn, scope) {
    for(var i = 0, len = this.length; i < len; ++i) {
      fn.call(scope, this[i], i, this);
    }
  }
}