How to correctly iterate through getElementsByClassName

According to MDN, the way to retrieve an item from a NodeList is:

nodeItem = nodeList.item(index)

Thus:

var slides = document.getElementsByClassName("slide");
for (var i = 0; i < slides.length; i++) {
   Distribute(slides.item(i));
}

I haven't tried this myself (the normal for loop has always worked for me), but give it a shot.


If you use the new querySelectorAll you can call forEach directly.

document.querySelectorAll('.edit').forEach(function(button) {
    // Now do something with my button
});

Per the comment below. nodeLists do not have a forEach function.

If using this with babel you can add Array.from and it will convert non node lists to a forEach array. Array.from does not work natively in browsers below and including IE 11.

Array.from(document.querySelectorAll('.edit')).forEach(function(button) {
    // Now do something with my button
});

At our meetup last night I discovered another way to handle node lists not having forEach

[...document.querySelectorAll('.edit')].forEach(function(button) {
    // Now do something with my button
});

Browser Support for [...]

Showing as Node List

Showing as Node List

Showing as Array

Showing as Array


An up-to-date answer in 2021

When this question was asked (2013), .getElementsBy* methods returned a NodeList. However, that's not the case in 2021, all these DOM traversing methods return a live HTMLCollection, getElementsByName being an exception.

There are remarkable differencences between these two lists. Whereas HTMLCollection has two methods, NodeList has five methods, including NodeList.forEach, which can be used to iterate through a NodeList.

Live collections are problematic because there's no way to keep the collection updated under the hood. To achieve a reliable collection, the DOM is traversed every time a collection is accessed, in every current implementation of HTMLCollection. In practice this means, that every time you access a member of a live collection (including the length), the browser traverses the entire document to find the specific element.

The Standard says:

If a collection is live, then the attributes and methods on that object must operate on the actual underlying data, not a snapshot of the data.

Never iterate live HTMLCollection!

Instead, convert the collection to array, and iterate that array. Or rather get the elements using .querySelectorAll, which gives you a static NodeList and a more flexible way to select elements.

If you really need a live list of elements, use the closest possible common ancestor element as the context instead of document.

It's notable, that also live NodeLists exist. Examples of live NodeLists are Node.childNodes and the return value of getElementsByName.


You could always use array methods:

var slides = getElementsByClassName("slide");
Array.prototype.forEach.call(slides, function(slide, index) {
    Distribute(slides.item(index));
});