Dmitrii Bundin Dmitrii Bundin - 2 months ago 119
Javascript Question

foreach loop for HTMLCollection elements

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

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

But I got the follwoing output in console:


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


Eeek. You can't iterate over a nodeList or HTMLCollection with for/in and when you do iterate, you need to actually retrieve the value from the list, using the index in your iteration.

You should iterate it like this:

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

for/in is meant for iterating the properties of an object. It is not meant for iterating an array or an array-like object which an HTMLCollection is. 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 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):


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.

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) {

Working demo (in Firefox, Chrome and Edge as of April 2016):

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) {

This works in the current version of Chrome, Firefox and Edge.

Working demo: