Coder Perfect

Array.forEach is used to go over the results of getElementsByClassName in JS.

Problem

I’m going to iterate over some DOM elements, so here’s how I’m going to accomplish it:

document.getElementsByClassName( "myclass" ).forEach( function(element, index, array) {
  //do stuff
});

However, I receive the following error:

Because I’m using Firefox 3, I know getElementsByClassName and Array.forEach are available. This works perfectly:

[2, 5, 9].forEach( function(element, index, array) {
  //do stuff
});

Is getElementsByClassName’s output an array? What is it if it isn’t?

Asked by Steve Claridge

Solution #1

No, it’s an HTMLCollection (at least in recent browsers), as described in DOM4. A NodeList was returned by older browsers.

You may call Array’s forEach method in all modern browsers (pretty much anything other than Internet Explorer 8), supplying the list of elements (HTMLCollection or NodeList) as the this value:

var els = document.getElementsByClassName("myclass");

Array.prototype.forEach.call(els, function(el) {
    // Do stuff here
    console.log(el.tagName);
});

// Or
[].forEach.call(els, function (el) {...});

You can use Array.from: if you’re in the fortunate position of being able to utilize ES6 (i.e. you can safely ignore Internet Explorer or you’re using an ES5 transpiler).

Array.from(els).forEach((el) => {
    // Do stuff here
    console.log(el.tagName);
});

Answered by Tim Down

Solution #2

You can convert a collection to an array using Array.from instead of Array.prototype.forEach.call:

Array.from(document.getElementsByClassName("myclass")).forEach(
    function(element, index, array) {
        // do stuff
    }
);

You’ll need to use something like Babel if you’re using an older browser that doesn’t support Array.from.

This syntax is also included in ES6:

[...document.getElementsByClassName("myclass")].forEach(
    (element, index, array) => {
        // do stuff
    }
);

Rest destructuring with… works on all array-like objects, not just arrays, and then the values are utilized to form an array using standard array syntax.

While the alternative function querySelectorAll (which effectively renders getElementsByClassName redundant) produces a collection with forEach built-in, other methods such as map and filter are not available, so this syntax remains useful:

[...document.querySelectorAll(".myclass")].map(
    (element, index, array) => {
        // do stuff
    }
);

[...document.querySelectorAll(".myclass")].map(element => element.innerHTML);

Answered by Athari

Solution #3

Or you can use querySelectorAll which returns NodeList:

document.querySelectorAll('.myclass').forEach(...)

Modern browsers (including Edge, but not Internet Explorer) support: Is it possible to use querySelectorAll NodeList.prototype.forEach with querySelectorAll NodeList.prototype.forEach? ()

MDN: Document.querySelectorAll()

Answered by icl7126

Solution #4

The code below still works, even if the return type has changed in newer versions of HTML (see Tim Down’s updated answer).

It’s a NodeList, as others have stated. You can try this entire, functional example:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <script>
            function findTheOddOnes()
            {
                var theOddOnes = document.getElementsByClassName("odd");
                for(var i=0; i<theOddOnes.length; i++)
                {
                    alert(theOddOnes[i].innerHTML);
                }
            }
        </script>
    </head>
    <body>
        <h1>getElementsByClassName Test</h1>
        <p class="odd">This is an odd para.</p>
        <p>This is an even para.</p>
        <p class="odd">This one is also odd.</p>
        <p>This one is not odd.</p>
        <form>
            <input type="button" value="Find the odd ones..." onclick="findTheOddOnes()">
        </form>
    </body>
</html>

On Windows 7, this works on Internet Explorer 9, Firefox 5, Safari 5, and Chrome 12.

Answered by james.garriss

Solution #5

getElementsByClassName() returns an array-like object rather than an Array. It’s referred to as an HTMLCollection, as opposed to a NodeList (which has its own forEach() method).

The spread operator or spread syntax is a simple approach to convert an array-like object for usage with Array.prototype.forEach() in ES2015 that hasn’t been addressed yet:

const elementsArray = document.getElementsByClassName('myclass');

[...elementsArray].forEach((element, index, array) => {
    // do something
});

Answered by Kloptikus

Post is based on https://stackoverflow.com/questions/3871547/js-iterating-over-result-of-getelementsbyclassname-using-array-foreach