JS: itération du résultat de getElementsByClassName en utilisant Array.forEach

je veux itérer sur quelques éléments DOM, je fais ceci:

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

mais je reçois une erreur: document.getElementsByClassName ("myclass").forEach n'est pas une fonction

J'utilise Firefox 3 donc je sais que les deux getElementsByClassName et Array.forEach sont présents. Cela fonctionne très bien:

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

est-ce que le résultat de getElementsByClassName est un tableau? Si non, quel est-il?

138
demandé sur August Lilleaas 2010-10-06 14:28:03

8 réponses

Pas de. Comme spécifié dans DOM4 , c'est un HTMLCollection (dans les navigateurs modernes, au moins. Les navigateurs plus anciens ont retourné un NodeList ).

dans tous les navigateurs modernes (à peu près tout autre IE < = 8), Vous pouvez appeler la méthode forEach de Array, en lui passant la liste des éléments (que ce soit HTMLCollection ou NodeList ) comme la valeur this :

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) {...});
220
répondu Tim Down 2015-12-17 15:23:22

vous pouvez utiliser Array.from pour convertir la collection en tableau, qui est beaucoup plus propre que Array.prototype.forEach.call :

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

dans les navigateurs plus anciens qui ne prennent pas en charge Array.from , vous devez utiliser quelque chose comme Babel.


ES6 ajoute également cette syntaxe:

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

Rest destructuring with ... fonctionne sur tous les objets en forme de tableau, non seulement les tableaux eux-mêmes, puis bon vieux tableau la syntaxe est utilisée pour construire un tableau de valeurs.


alors que la fonction alternative querySelectorAll (qui rend en quelque sorte getElementsByClassName obsolète) renvoie une collection qui a forEach nativement, d'autres méthodes comme map ou filter sont manquantes, donc cette syntaxe est encore utile:

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

[...document.querySelectorAll(".myclass")].map(element => element.innerHTML);
35
répondu Athari 2018-01-06 02:23:26

Edit: bien que le type de retour ait changé dans les nouvelles versions de HTML (voir la réponse mise à jour de Tim Down), le code ci-dessous fonctionne toujours.

comme d'autres l'ont dit, c'est un NodeList. Voici un exemple complet et fonctionnel que vous pouvez essayer:

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

cela fonctionne dans IE 9, FF 5, Safari 5, et Chrome 12 sur Win 7.

13
répondu james.garriss 2015-05-21 14:04:37

ou vous pouvez utiliser querySelectorAll qui retourne NodeList :

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

pris en charge par les navigateurs modernes (y compris Edge, mais pas IE):

puis-je utiliser querySelectorAll

NodeList.prototype.forEach ()

MDN: Document.querySelectorAll ()

10
répondu icl7126 2017-08-19 13:02:50

est-ce que le résultat de getElementsByClassName est un tableau?

Non

sinon, qu'est-ce que c'est?

comme pour toutes les méthodes DOM qui renvoient plusieurs éléments, C'est une NodeList, voir https://developer.mozilla.org/en/DOM/document.getElementsByClassName

5
répondu Quentin 2010-10-06 10:31:03

le résultat de getElementsByClassName() n'est pas un tableau, mais un objet semblable à un tableau . Spécifiquement, il est appelé un HTMLCollection , à ne pas confondre avec NodeList ( qui a son propre forEach() méthode ).

un moyen simple avec ES2015 pour convertir un objet de type tableau pour une utilisation avec Array.prototype.forEach() qui n'a pas encore été mentionné est d'utiliser l'opérateur de propagation ou syntaxe de propagation :

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

[...elementsArray].forEach((element, index, array) => {
    // do something
});
4
répondu Kloptikus 2017-10-03 00:00:15

comme déjà dit, getElementsByClassName retourne un HTMLCollection , qui est défini comme

[Exposed=Window]
interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

auparavant, certains navigateurs renvoyaient un NodeList à la place.

[Exposed=Window]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};

la différence est importante, car DOM4 définit maintenant NodeList s comme itérable.

selon Web IDL draft,

Objets implémentant une interface qui est déclarée itérable soutien itéré pour obtenir une séquence de valeurs.

Note : dans la reliure du langage ECMAScript, une interface qui est itérable aura des "entrées", "forEach", "touches", "valeurs" et @@iterator propriétés sur son interface objet prototype .

cela signifie que, si vous voulez utiliser forEach , vous pouvez utiliser une méthode DOM qui retourne un NodeList , comme querySelectorAll .

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

notez que cela n'est pas encore largement soutenu. Voir aussi pour chaque méthode de Noeud.childNodes?

2
répondu Oriol 2017-05-23 11:47:20

Il ne renvoie pas un Array , il renvoie un NodeList .

0
répondu reko_t 2010-10-06 10:30:56