Start · Sprachen · JavaScript · Referenz · TreeWalker.nextNode()

TreeWalker.nextNode()

Methode

Setzt <code>currentNode</code> auf den nächsten sichtbaren Knoten in Dokumentreihenfolge und gibt ihn zurück, oder <code>null</code>, wenn keiner mehr existiert.

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

Signatur

TreeWalker.prototype.nextNode()

Beschreibung

nextNode() ist die zentrale Methode, um mit einem TreeWalker einen DOM-Teilbaum der Reihe nach zu durchlaufen. Sie läuft vom aktuellen Knoten (currentNode) aus in Dokumentreihenfolge (Tiefensuche, Präorder) weiter: zuerst zu den Kindern, dann zu den Geschwistern, dann zu den Geschwistern der Vorfahren, aber nie über den Wurzelknoten (root) hinaus.

„Sichtbar“ heißt dabei: Der Knoten passt zum whatToShow-Filter (z. B. NodeFilter.SHOW_ELEMENT oder NodeFilter.SHOW_TEXT) und der optionale filter-Callback gibt NodeFilter.FILTER_ACCEPT zurück. Bei FILTER_SKIP wird nur der Knoten selbst übersprungen, seine Kinder werden weiter untersucht. Bei FILTER_REJECT wird der ganze Teilbaum ausgelassen.

Wird ein passender Knoten gefunden, setzt die Methode currentNode auf diesen Knoten und gibt ihn zurück. Gibt es keinen weiteren, liefert sie null, und currentNode bleibt unverändert. Deshalb eignet sich das Muster while ((node = walker.nextNode())) gut für Schleifen.

Typische Anwendungsfälle sind das Sammeln aller Textknoten (z. B. für Suchen und Hervorheben), das Durchsuchen von Elementen nach eigenen Kriterien oder die Verarbeitung von Kommentarknoten. querySelectorAll kann das nicht, weil es nur Elemente liefert.

Rückgabewert

Typ
Node | null
Beschreibung
Den nächsten sichtbaren Knoten, der dann auch currentNode ist, oder null, wenn im Teilbaum unterhalb von root kein weiterer Knoten existiert.

Beispiele

Alle Textknoten eines Artikels sammeln

const article = document.querySelector('article');
const walker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);

const texts = [];
let node;
while ((node = walker.nextNode())) {
  const text = node.nodeValue.trim();
  if (text) texts.push(text);
}
console.log(texts);
["Überschrift", "Erster Absatz …", "Zweiter Absatz …"]

Elemente mit eigenem Filter: Teilbäume per FILTER_REJECT auslassen

// Alle Links finden, aber nichts innerhalb von <nav>
const walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT,
  {
    acceptNode: (el) => {
      if (el.tagName === 'NAV') return NodeFilter.FILTER_REJECT; // ganzer Teilbaum weg
      if (el.tagName === 'A') return NodeFilter.FILTER_ACCEPT;
      return NodeFilter.FILTER_SKIP; // Knoten überspringen, Kinder prüfen
    }
  }
);

const links = [];
for (let el = walker.nextNode(); el; el = walker.nextNode()) {
  links.push(el.href);
}
console.log(`${links.length} Links außerhalb der Navigation`);
12 Links außerhalb der Navigation

Suchbegriff in Textknoten hervorheben

const highlight = (root, term) => {
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
  const matches = [];
  // Erst sammeln, dann ändern, damit das Umbauen die Traversierung nicht stört
  while (walker.nextNode()) {
    if (walker.currentNode.nodeValue.includes(term)) matches.push(walker.currentNode);
  }
  for (const textNode of matches) {
    const idx = textNode.nodeValue.indexOf(term);
    const hit = textNode.splitText(idx);
    hit.splitText(term.length);
    const mark = document.createElement('mark');
    hit.replaceWith(mark);
    mark.append(hit);
  }
  return matches.length;
};

console.log(highlight(document.body, 'JavaScript'));
3

Kommentarknoten auslesen

const walker = document.createTreeWalker(document, NodeFilter.SHOW_COMMENT);
while (walker.nextNode()) {
  console.log('Kommentar:', walker.currentNode.data.trim());
}
Kommentar: Build 2024-05-01

// Wichtig · Fallstricke

  • Der Wurzelknoten selbst wird nicht geliefert: Direkt nach dem Erzeugen ist currentNode === root. Der erste Aufruf von nextNode() gibt also den ersten Nachfolger zurück. Soll root mitgeprüft werden, muss man das separat tun.
  • Bei null bleibt currentNode gleich: Er zeigt dann auf den letzten gefundenen Knoten, nicht auf null.
  • DOM-Änderungen während der Traversierung: Anders als ein NodeIterator passt sich ein TreeWalker nicht an Änderungen an. Entfernt man currentNode aus dem DOM, führt nextNode() ab dessen alter Position weiter und landet eventuell außerhalb von root. Deshalb besser erst sammeln und danach ändern.
  • FILTER_REJECT und FILTER_SKIP verhalten sich im TreeWalker unterschiedlich. Bei einem NodeIterator dagegen wirken beide wie SKIP.
  • Der Filter kann eine Funktion oder ein Objekt mit einer Methode acceptNode sein. Wirft der Filter eine Ausnahme, bricht nextNode() ab. Ruft der Filter selbst den Walker auf, wird ein InvalidStateError ausgelöst.
  • Bei großen Dokumenten ist ein TreeWalker meist schneller und sparsamer als rekursives Durchlaufen von childNodes. Er wird von allen modernen Browsern unterstützt, auch vom Internet Explorer ab Version 9.