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 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));
});