Start · Sprachen · JavaScript · Referenz · NodeIterator

NodeIterator

Schnittstelle

Ein Iterator, der die Knoten eines DOM-Teilbaums als flache Liste in Dokumentreihenfolge durchläuft, optional nach Knotentyp und eigener Filterfunktion gefiltert.

seit JavaScript Baseline: alle Browser (DOM Level 2 Traversal) Kategorie: webapi

Signatur

interface NodeIterator

Beschreibung

NodeIterator durchläuft alle Knoten unterhalb eines Wurzelknotens (root) als flache Liste in Dokumentreihenfolge (Tiefensuche, Pre-Order). Eine Instanz legt man nicht mit einem Konstruktor an, sondern über document.createNodeIterator(root, whatToShow, filter). Mit nextNode() geht man vorwärts, mit previousNode() rückwärts. Ist das Ende erreicht, liefern beide null.

Anders als querySelectorAll() findet ein NodeIterator nicht nur Elemente. Er erfasst auch Textknoten, Kommentare und Verarbeitungsanweisungen. Die Bitmaske whatToShow (z. B. NodeFilter.SHOW_TEXT oder NodeFilter.SHOW_COMMENT) legt fest, welche Knotentypen berücksichtigt werden. Eine optionale Filterfunktion kann jeden Knoten zusätzlich mit NodeFilter.FILTER_ACCEPT annehmen oder mit FILTER_REJECT bzw. FILTER_SKIP überspringen.

Wichtige Eigenschaften (nur lesbar):

  • root: der Wurzelknoten der Iteration
  • whatToShow: die verwendete Bitmaske
  • filter: der übergebene Filter oder null
  • referenceNode: der Knoten, an dem der Iterator gerade steht
  • pointerBeforeReferenceNode: true, wenn der Zeiger vor dem Referenzknoten steht

Die Methode detach() hat heute keine Wirkung mehr. Einsatzgebiete sind z. B. alle Textknoten für Suchen und Hervorheben einsammeln, Kommentare auswerten oder große DOM-Bereiche ohne Rekursion durchlaufen. Wenn du die Baumstruktur brauchst (Eltern, Geschwister, Kinder), nimm stattdessen TreeWalker.

Parameter

Name Typ Default Beschreibung
$root Pflicht Node Parameter von document.createNodeIterator(): der Wurzelknoten, ab dem iteriert wird. Er selbst ist der erste Kandidat.
$whatToShow number NodeFilter.SHOW_ALL (0xFFFFFFFF) Bitmaske aus NodeFilter.SHOW_*-Konstanten, mehrere verknüpft mit |, z. B. NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT.
$filter NodeFilter | ((node: Node) => number) | null null Funktion oder Objekt mit einer Methode acceptNode(node). Rückgabe: NodeFilter.FILTER_ACCEPT, FILTER_REJECT oder FILTER_SKIP. Bei NodeIterator wirken REJECT und SKIP gleich.

Rückgabewert

Typ
NodeIterator
Beschreibung
document.createNodeIterator() gibt eine neue NodeIterator-Instanz zurück. nextNode() und previousNode() geben jeweils einen Node zurück oder null, wenn keine weiteren Knoten vorhanden sind.

Beispiele

Alle Textknoten eines Bereichs sammeln

document.body.innerHTML = '<article id="post"><h2>Titel</h2><p>Hallo <b>Welt</b></p></article>';

const root = document.getElementById('post');
const iterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);

const texte = [];
let node;
while ((node = iterator.nextNode())) {
  texte.push(node.nodeValue);
}
console.log(texte);
["Titel", "Hallo ", "Welt"]

Mit Filterfunktion: leere Textknoten überspringen

const iterator = document.createNodeIterator(
  document.body,
  NodeFilter.SHOW_TEXT,
  (node) => node.nodeValue.trim()
    ? NodeFilter.FILTER_ACCEPT
    : NodeFilter.FILTER_REJECT
);

let anzahlWoerter = 0;
for (let n = iterator.nextNode(); n; n = iterator.nextNode()) {
  anzahlWoerter += n.nodeValue.trim().split(/\s+/).length;
}
console.log(`Wörter auf der Seite: ${anzahlWoerter}`);
Wörter auf der Seite: 42

Kommentare finden und entfernen

document.body.innerHTML = '<div><!-- TODO --><p>Inhalt</p><!-- debug --></div>';

const iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_COMMENT);
const kommentare = [];
let c;
while ((c = iterator.nextNode())) kommentare.push(c);

// Erst sammeln, dann entfernen
kommentare.forEach((k) => k.remove());
console.log(kommentare.map((k) => k.data.trim()), document.body.innerHTML);
["TODO", "debug"] "<div><p>Inhalt</p></div>"

Vorwärts und rückwärts navigieren

document.body.innerHTML = '<ul><li>A</li><li>B</li><li>C</li></ul>';

const it = document.createNodeIterator(
  document.querySelector('ul'),
  NodeFilter.SHOW_ELEMENT,
  (n) => n.tagName === 'LI' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
);

console.log(it.nextNode().textContent);     // A
console.log(it.nextNode().textContent);     // B
console.log(it.previousNode().textContent); // B (Zeiger kehrt um)
console.log(it.pointerBeforeReferenceNode);
A B B true

// Wichtig · Fallstricke

  • Richtungswechsel: Der Iterator steht immer zwischen zwei Knoten. Rufst du nach nextNode() direkt previousNode() auf, bekommst du denselben Knoten noch einmal.
  • FILTER_REJECT und FILTER_SKIP: Bei NodeIterator überspringen beide nur den einzelnen Knoten, seine Nachfahren werden trotzdem besucht. Nur bei TreeWalker schließt FILTER_REJECT den ganzen Teilbaum aus.
  • DOM-Änderungen: Der Iterator bleibt gültig, wenn sich das DOM ändert. Wird der Referenzknoten entfernt, rückt er automatisch weiter. Trotzdem ist es übersichtlicher, Knoten erst zu sammeln und danach zu verändern.
  • Kein JS-Iterator: NodeIterator setzt Symbol.iterator nicht um. for...of und der Spread-Operator funktionieren daher nicht direkt, du brauchst eine while-Schleife oder eine eigene Generatorfunktion.
  • Die Filterfunktion darf das DOM nicht verändern. Wirft sie eine Ausnahme, bricht die Iteration ab.
  • detach() ist veraltet und hat keine Wirkung. Die früheren Parameter SHOW_ENTITY, SHOW_NOTATION usw. sind ebenfalls veraltet.
  • Kompatibilität: Wird von allen modernen Browsern (und seit IE9) unterstützt. Für reine Elementsuchen ist querySelectorAll() meist einfacher und schneller.