webentwicklung-frage-antwort-db.com.de

JS: Durchlaufen des Ergebnisses von getElementsByClassName mithilfe von Array.forEach

Ich möchte einige DOM-Elemente durchlaufen. Ich mache Folgendes:

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

aber ich bekomme eine Fehlermeldung: document.getElementsByClassName ("myclass"). forEach ist keine Funktion

Ich benutze Firefox 3, damit ich weiß, dass sowohl getElementsByClassName als auch Array.forEach sind anwesend. Das funktioniert gut:

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

Ist das Ergebnis von getElementsByClassName ein Array? Wenn nicht, was ist das?

191
Steve Claridge

Nein. Als angegeben in DOM4 ist es ein HTMLCollection (zumindest in modernen Browsern. Ältere Browser gaben ein NodeList ).

In allen modernen Browsern (so ziemlich alles andere IE <= 8)) können Sie die Methode forEach von Array aufrufen und dabei die Liste der Elemente übergeben (sei es HTMLCollection oder NodeList) als this Wert:

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

Wenn Sie in der glücklichen Lage sind, ES6 verwenden zu können (d. H. Sie können Internet Explorer ignorieren oder einen ES5-Transpiler verwenden), können Sie Array.from :

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

Sie können Array.from Verwenden, um eine Sammlung in ein Array zu konvertieren. Dies ist viel sauberer als Array.prototype.forEach.call:

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

In älteren Browsern, die Array.from Nicht unterstützen, müssen Sie so etwas wie Babel verwenden.


ES6 fügt auch diese Syntax hinzu:

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

Die Rest-Destrukturierung mit ... Funktioniert für alle Array-ähnlichen Objekte, nicht nur für Arrays selbst. Dann wird eine gute alte Array-Syntax verwendet, um ein Array aus den Werten zu erstellen.


Während die alternative Funktion querySelectorAll (die getElementsByClassName irgendwie überflüssig macht) eine Sammlung zurückgibt, die forEach enthält, können andere Methoden wie map oder filter fehlen, daher ist diese Syntax immer noch nützlich:

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

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

Oder Sie können querySelectorAll verwenden, das NodeList zurückgibt:

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

Unterstützt von modernen Browsern (einschließlich Edge, aber nicht IE):
Kann ich querySelectorAll verwenden?
NodeList.prototype.forEach ()

MDN: Document.querySelectorAll ()

18
icl7126

Bearbeiten: Obwohl sich der Rückgabetyp in neuen HTML-Versionen geändert hat (siehe die aktualisierte Antwort von Tim Down), funktioniert der folgende Code immer noch.

Wie andere gesagt haben, ist es eine NodeList. Hier ist ein vollständiges, funktionierendes Beispiel, das Sie ausprobieren können:

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

Dies funktioniert in IE 9, FF 5, Safari 5 und Chrome 12 unter Win 7.

14
james.garriss

Das Ergebnis von getElementsByClassName() ist kein Array, sondern ein arrayartiges Objekt . Insbesondere wird es HTMLCollection genannt, nicht zu verwechseln mit NodeList ( das seine eigene forEach()-Methode hat ).

Eine einfache Möglichkeit mit ES2015, ein Array-ähnliches Objekt für die Verwendung mit Array.prototype.forEach() zu konvertieren, das noch nicht erwähnt wurde, ist die Verwendung des Operators spread oder spread syntax :

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

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

Ist das Ergebnis von getElementsByClassName ein Array?

Nein

Wenn nicht, was ist das?

Wie bei allen DOM-Methoden, die mehrere Elemente zurückgeben, handelt es sich um eine NodeList (siehe https://developer.mozilla.org/en/DOM/document.getElementsByClassName )

5
Quentin

Wie bereits gesagt, gibt getElementsByClassName eine HTMLCollection zurück, die definiert ist als

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

Bisher gaben einige Browser stattdessen ein NodeList zurück.

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

Der Unterschied ist wichtig, da DOM4 jetzt NodeList s als iterierbar definiert.

Gemäß Web IDL Entwurf,

Objekte, die eine als iterabel deklarierte Schnittstelle implementieren, unterstützen das Iterieren, um eine Folge von Werten zu erhalten.

Hinweis : In der ECMAScript-Sprachbindung enthält eine durchlaufende Schnittstelle "Einträge", "für jeden", "Schlüssel", "Werte" und - @@ iterator Eigenschaften auf seinem Interface-Prototyp-Objekt .

Das bedeutet, dass Sie, wenn Sie forEach verwenden möchten, eine DOM-Methode verwenden können, die eine NodeList zurückgibt, wie querySelectorAll .

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

Beachten Sie, dass dies noch nicht allgemein unterstützt wird. Siehe auch für jede Methode von Node.childNodes?

3
Oriol

Es wird kein Array zurückgegeben, sondern ein NodeList .

0
reko_t

Dies ist der sicherere Weg:

var elements = document.getElementsByClassName("myclass");
for (var i = 0; i < elements.length; i++) myFunction(elements[i]);
0
gildniy

getElementsByClassName gibt HTMLCollection in modernen Browsern zurück.

das ist ein Array-ähnliches Objekt, das den Argumenten ähnelt. Es kann durch die for...of - Schleife iteriert werden. Siehe unten was MDN doc sagt darüber:

Die Anweisung for ... of erstellt eine Schleife, die über iterierbare Objekte iteriert, einschließlich: eingebauter String, Array, Array-ähnliche Objekte (z. B. Argumente oder NodeList), TypedArray, Map, Set und benutzerdefinierte Iterables. Es ruft einen benutzerdefinierten Iterations-Hook mit Anweisungen auf, die für den Wert jeder einzelnen Eigenschaft des Objekts ausgeführt werden sollen.

Beispiel

for (let element of getElementsByClassName("classname")){
   element.style.display="none";
}
0
Haritsinh Gohil