Iteration über das Ergebnis von getElementsByClassName mit Array.forEach

Lesezeit: 5 Minuten

Benutzer-Avatar
Steve Claridge

Ich möchte über einige DOM-Elemente iterieren, ich mache das:

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

aber ich bekomme einen Fehler:

document.getElementsByClassName(“myclass”).forEach ist keine Funktion

Ich benutze Firefox 3, also kenne ich beides getElementsByClassName und Array.forEach sind anwesend. Das funktioniert gut:

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

Ist das Ergebnis von getElementsByClassName eine Anordnung? Wenn nicht, was ist es?

Benutzer-Avatar
Athari

Sie können verwenden Array.from um eine Sammlung in ein Array umzuwandeln, was viel sauberer ist als Array.prototype.forEach.call:

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

In älteren Browsern, die das nicht unterstützen Array.frommüssen Sie so etwas wie Babel verwenden.


ES6 fügt auch diese Syntax hinzu:

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

Rest destrukturierend mit ... funktioniert mit allen Array-ähnlichen Objekten, nicht nur mit Arrays selbst, dann wird die gute alte Array-Syntax verwendet, um ein Array aus den Werten zu konstruieren.


Während die alternative Funktion querySelectorAll (was irgendwie macht getElementsByClassName veraltet) gibt eine Auflistung zurück, die vorhanden ist forEach nativ, 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);

  • Hinweis: Ohne das vorgeschlagene Transpilling (Babel) ist dies NICHT kompatibel mit IE < Edge, Opera, Safari < 9, Android-Browser, Chrome für Android usw.) Quelle: Mozilla-Entwicklerdokumentation

    – Sean

    5. September 2016 um 5:53 Uhr


  • Beachten Sie die Leistungseinbuße gegenüber getElementByClassName

    – Szabolcs Páll

    30. August 2018 um 14:20 Uhr

  • Die Leistungseinbuße ist vernachlässigbar im Vergleich zu anderen intensiveren Aufgaben wie dem Ändern von DOM. Wenn ich ausführe 60.000 davon in 1 Millisekundeich bin mir ziemlich sicher, dass es kein Problem für eine vernünftige Verwendung sein wird 🙂

    – icl7126

    31. Juli 2019 um 13:13 Uhr


  • Du hast den falschen Benchmark verlinkt. Hier ist das Richtige measurethat.net/Benchmarks/Show/4076/0/… Ich habe es gerade auf meinem Low-End-Telefon ausgeführt und 160 k / s gegenüber 380 k / s erhalten. Da Sie DOM-Manipulation erwähnt haben, hier ist das auch measurethat.net/Benchmarks/Show/5705/0/… Habe 50k/s gegenüber 130k/s. Wie Sie sehen, ist es noch langsamer, DOM zu manipulieren, wahrscheinlich weil NodeList statisch ist (wie von anderen erwähnt). In den meisten Anwendungsfällen immer noch vernachlässigbar, aber dennoch fast 3-mal langsamer.

    – Szabolcs Páll

    1. August 2019 um 6:43 Uhr

  • IE unterstützt die forEach-Methode auch nicht für NodeList. Aber es gibt eine Problemumgehung wie die Verwendung des Spread-Operators oder Array.from

    – Melchia

    13. Oktober 2020 um 9:54 Uhr

Benutzer-Avatar
Haritsinh Gohil

getElementsByClassName kehrt zurück HTMLCollection in modernen Browsern.

welches ist
Array-ähnliches Objekt, ähnlich wie Argumente was iterierbar ist for...of Schleife siehe unten was MDN Doc sagt dazu:

Das Die for…of-Anweisung erstellt eine Schleife, die über iterierbare Objekte iterierteinschließlich: eingebauter String, Array, Array-ähnliche Objekte (z. B. arguments
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.

Javascript-Beispiel

for (const element of document.getElementsByClassName("classname")){
   element.style.display="none";
}

Typoskript-Beispiel

let elements = document.getElementsByClassName('classname');
let i;

for (i = 0; i < elements.length; i++) {

  if (elements[i] instanceof HTMLElement) {
    elements[i].style.display = "none";
  }

}

  • Nicht so, laut Typescript: error TS2488: Type 'HTMLCollectionOf<Element>' must have a '[Symbol.iterator]()' method that returns an iterator.

    – Schildkröten sind süß

    1. Januar 2020 um 7:37 Uhr

  • @TurtlesAreCute, hier verwendet OP Javascript und kein Typoskript, und ich habe gemäß der Empfehlung von Vanilla js geantwortet, sodass es in Typoskript eine andere Lösung für das Problem sein kann.

    – Haritsinh Gohil

    1. Januar 2020 um 7:46 Uhr


  • @TurtlesAreCute, übrigens funktioniert es auch in Typoskript, aber Sie müssen den richtigen Variablentyp erwähnen, der das Element einer bestimmten CSS-Klasse enthält, damit es entsprechend umgewandelt werden kann, für Details siehe diese Antwort.

    – Haritsinh Gohil

    1. Januar 2020 um 8:12 Uhr

  • Dies ist mit Sicherheit die beste Antwort und funktioniert in Typescript einwandfrei.

    – Timmm

    23. Oktober 2020 um 19:57 Uhr

  • @NateS was Sie tun können, ist das zu bekommen HTMLCollection in die Variable und deklariere sie als Typ any und es wird funktionieren, wie es in Javascript funktioniert.

    – Haritsinh Gohil

    21. Juni 2021 um 7:21 Uhr

Benutzer-Avatar
vergoldet

Das ist der sicherere Weg:

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

  • Nicht so, laut Typescript: error TS2488: Type 'HTMLCollectionOf<Element>' must have a '[Symbol.iterator]()' method that returns an iterator.

    – Schildkröten sind süß

    1. Januar 2020 um 7:37 Uhr

  • @TurtlesAreCute, hier verwendet OP Javascript und kein Typoskript, und ich habe gemäß der Empfehlung von Vanilla js geantwortet, sodass es in Typoskript eine andere Lösung für das Problem sein kann.

    – Haritsinh Gohil

    1. Januar 2020 um 7:46 Uhr


  • @TurtlesAreCute, übrigens funktioniert es auch in Typoskript, aber Sie müssen den richtigen Variablentyp erwähnen, der das Element einer bestimmten CSS-Klasse enthält, damit es entsprechend umgewandelt werden kann, für Details siehe diese Antwort.

    – Haritsinh Gohil

    1. Januar 2020 um 8:12 Uhr

  • Dies ist mit Sicherheit die beste Antwort und funktioniert in Typescript einwandfrei.

    – Timmm

    23. Oktober 2020 um 19:57 Uhr

  • @NateS was Sie tun können, ist das zu bekommen HTMLCollection in die Variable und deklariere sie als Typ any und es wird funktionieren, wie es in Javascript funktioniert.

    – Haritsinh Gohil

    21. Juni 2021 um 7:21 Uhr

Hier ist ein Test, den ich auf jsperf erstellt habe:
https://jsperf.com/vanillajs-loop-through-elements-of-class

Die leistungsstärkste Variante in Chrome und Firefox ist die gute alte for-Schleife in Kombination mit document.getElementsByClassName:

var elements = document.getElementsByClassName('testClass'), elLength = elements.length;
for (var i = 0; i < elLength; i++) {
    elements.item(i).textContent="Tested";
};

In Safari ist diese Variante der Gewinner:

var elements = document.querySelectorAll('.testClass');
elements.forEach((element) => {
    element.textContent="Tested";
});

Wenn Sie die leistungsfähigste Variante für alle Browser wollen, könnte es diese sein:

var elements = document.getElementsByClassName('testClass');
Array.from(elements).map(
    (element) => {
        return element.textContent="Tested";
    }
);

1010770cookie-checkIteration über das Ergebnis von getElementsByClassName mit Array.forEach

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy