Signatur
Beschreibung
Mit NodeList.prototype.forEach() durchläufst du alle Knoten einer NodeList, ohne sie vorher in ein Array umzuwandeln. Typischerweise stammt die Liste aus document.querySelectorAll() oder Node.childNodes. Für jeden Eintrag wird die Rückruffunktion mit dem aktuellen Knoten, seinem Index und der Liste selbst aufgerufen.
Die Methode verhält sich wie Array.prototype.forEach(): Sie gibt undefined zurück und lässt sich weder mit break noch mit return vorzeitig abbrechen. Wenn du abbrechen, filtern oder abbilden willst, wandle die Liste mit Array.from() oder dem Spread-Operator in ein echtes Array um oder verwende eine for...of-Schleife.
Wichtig ist der Unterschied zwischen statischen und live NodeLists: Die Liste aus querySelectorAll() ist statisch. Änderungen am DOM während des Durchlaufs wirken sich also nicht auf sie aus. childNodes ist dagegen live. Entfernst oder fügst du dort während der Schleife Knoten ein, können Einträge übersprungen oder doppelt verarbeitet werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $callback Pflicht | (currentValue: Node, currentIndex: number, listObj: NodeList) => void | Funktion, die für jeden Knoten aufgerufen wird. Sie bekommt drei Argumente: currentValue (den aktuellen Knoten), currentIndex (seinen Index) und listObj (die NodeList, auf der forEach() aufgerufen wurde). |
|
| $thisArg | any | undefined | Wert, der beim Ausführen von callback als this gilt. Bei Pfeilfunktionen hat er keine Wirkung, weil diese this aus dem umgebenden Gültigkeitsbereich übernehmen. |
Rückgabewert
Beispiele
Allen Buttons eine Klasse und einen Klick-Handler geben
const buttons = document.querySelectorAll('button.aktion');
buttons.forEach((button, index) => {
button.classList.add('bereit');
button.addEventListener('click', () => {
console.log(`Button ${index} geklickt: ${button.textContent}`);
});
});
Kindknoten inklusive Textknoten untersuchen
const liste = document.createElement('ul');
liste.innerHTML = '<li>Äpfel</li>\n<li>Birnen</li>';
liste.childNodes.forEach((node, i) => {
console.log(i, node.nodeName, JSON.stringify(node.textContent));
});
thisArg nutzen, um in einem Objekt zu sammeln
const statistik = {
anzahl: 0,
zaehle(node) {
if (node.nodeType === Node.ELEMENT_NODE) this.anzahl++;
}
};
document.body.childNodes.forEach(statistik.zaehle, statistik);
console.log(`Elemente direkt im body: ${statistik.anzahl}`);
Vorzeitig abbrechen: stattdessen for...of verwenden
const felder = document.querySelectorAll('input[required]');
// forEach kann nicht abbrechen – for...of schon
let erstesLeeresFeld = null;
for (const feld of felder) {
if (!feld.value.trim()) {
erstesLeeresFeld = feld;
break;
}
}
erstesLeeresFeld?.focus();
// Für filter/map vorher in ein Array umwandeln
const namen = [...felder].map((f) => f.name);
console.log(namen);
// Wichtig · Fallstricke
- Nur
forEach, kein vollständiges Array: Eine NodeList hat zwarforEach(),entries(),keys()undvalues(), aber wedermap()nochfilter()oderreduce(). Hier hilftArray.from(nodeList)oder[...nodeList]. HTMLCollectionhat keinforEach:getElementsByClassName(),getElementsByTagName()undelement.childrenliefern eineHTMLCollection. Ein Aufruf von.forEach()darauf wirft einenTypeError.- Live-Listen: Veränderst du
childNodeswährend des Durchlaufs, etwa durchnode.remove(), werden Einträge übersprungen. Kopiere die Liste vorher:[...el.childNodes].forEach(n => n.remove()). - Kein Abbruch, kein
await:returnim Callback überspringt nur den aktuellen Eintrag. Ist der Callbackasync, wartetforEachnicht auf die Promises. Für sequenzielles Warten nimmfor...ofmitawait. - Kompatibilität: Im Internet Explorer fehlt die Methode. Für ältere Umgebungen reicht ein Polyfill:
NodeList.prototype.forEach ??= Array.prototype.forEach;