Start · Sprachen · JavaScript · Referenz · Document.createTreeWalker()

Document.createTreeWalker()

Methode

Erzeugt ein <code>TreeWalker</code>-Objekt, mit dem man den DOM-Teilbaum unterhalb von <code>root</code> gefiltert in alle Richtungen durchlaufen kann.

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

Signatur

Document.prototype.createTreeWalker(root, whatToShow, filter)

Beschreibung

document.createTreeWalker() liefert ein TreeWalker-Objekt. Damit lässt sich ein DOM-Teilbaum Knoten für Knoten durchlaufen, ohne selbst eine Rekursion über childNodes schreiben zu müssen. Der Walker hat einen Zeiger (currentNode), den man mit nextNode(), previousNode(), parentNode(), firstChild(), lastChild(), nextSibling() und previousSibling() bewegt.

Über die Bitmaske whatToShow (Konstanten aus NodeFilter, z. B. NodeFilter.SHOW_TEXT oder NodeFilter.SHOW_ELEMENT) wird festgelegt, welche Knotentypen überhaupt in Frage kommen. Mit einem optionalen filter kann man zusätzlich pro Knoten entscheiden: NodeFilter.FILTER_ACCEPT (Knoten zurückgeben), FILTER_SKIP (Knoten auslassen, seine Kinder aber prüfen) oder FILTER_REJECT (Knoten und seinen ganzen Teilbaum auslassen).

Typische Einsatzgebiete sind das Suchen und Hervorheben von Text, das Einsammeln aller Textknoten (z. B. für Übersetzungen oder Wortzählungen), das Finden von Kommentarknoten oder fokussierbaren Elementen. Gegenüber querySelectorAll() hat der TreeWalker den Vorteil, dass er auch Text- und Kommentarknoten erreicht und bewegliche Navigation in beide Richtungen erlaubt.

Parameter

Name Typ Default Beschreibung
$root Pflicht Node Wurzelknoten des zu durchlaufenden Teilbaums. Er ist der Startwert von currentNode; der Walker verlässt diesen Teilbaum nie.
$whatToShow number NodeFilter.SHOW_ALL (0xFFFFFFFF) Bitmaske aus NodeFilter.SHOW_*-Konstanten, mit | kombinierbar, z. B. NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT.
$filter NodeFilter | ((node: Node) => number) | null null Funktion oder Objekt mit Methode acceptNode(node), das NodeFilter.FILTER_ACCEPT, FILTER_SKIP oder FILTER_REJECT zurückgibt.

Rückgabewert

Typ
TreeWalker
Beschreibung
Ein neues TreeWalker-Objekt, dessen currentNode auf root steht.

Beispiele

Alle nicht-leeren Textknoten einsammeln

const walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_TEXT,
  (node) => node.nodeValue.trim()
    ? NodeFilter.FILTER_ACCEPT
    : NodeFilter.FILTER_SKIP
);

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

Suchbegriff hervorheben, Skripte und Styles ausschließen

const highlight = (root, term) => {
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
    acceptNode(node) {
      const tag = node.parentElement?.tagName;
      if (tag === 'SCRIPT' || tag === 'STYLE') return NodeFilter.FILTER_REJECT;
      return node.nodeValue.includes(term)
        ? NodeFilter.FILTER_ACCEPT
        : NodeFilter.FILTER_SKIP;
    }
  });

  // Erst sammeln, dann ändern – sonst gerät der Walker durcheinander
  const hits = [];
  while (walker.nextNode()) hits.push(walker.currentNode);

  for (const textNode of hits) {
    const start = textNode.nodeValue.indexOf(term);
    const match = textNode.splitText(start);
    match.splitText(term.length);
    const mark = document.createElement('mark');
    match.replaceWith(mark);
    mark.append(match);
  }
  return hits.length;
};

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

Elemente mit FILTER_REJECT ganze Teilbäume überspringen lassen

const walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT,
  (el) => el.hidden || el.getAttribute('aria-hidden') === 'true'
    ? NodeFilter.FILTER_REJECT   // inkl. aller Kinder ignorieren
    : NodeFilter.FILTER_ACCEPT
);

let count = 0;
for (let n = walker.nextNode(); n; n = walker.nextNode()) count++;
console.log(`Sichtbare Elemente: ${count}`);
Sichtbare Elemente: 42

Rückwärts navigieren und Eltern ermitteln

const list = document.querySelector('ul');
const walker = document.createTreeWalker(list, NodeFilter.SHOW_ELEMENT);

walker.lastChild();              // springt zum letzten <li>
console.log(walker.currentNode.textContent);
walker.previousSibling();        // vorheriges <li>
console.log(walker.currentNode.textContent);
console.log(walker.parentNode() === list);
Punkt 3 Punkt 2 true

// Wichtig · Fallstricke

  • Der Wurzelknoten selbst wird von nextNode() nicht zurückgegeben – der erste Aufruf liefert den ersten passenden Nachfahren. Soll root mitgeprüft werden, muss man walker.currentNode vor der Schleife auswerten.
  • DOM während des Durchlaufs ändern: Wird der aktuelle Knoten entfernt oder ersetzt, kann der Walker Knoten überspringen oder abbrechen. Besser erst Treffer in einem Array sammeln und danach ändern.
  • FILTER_SKIP vs. FILTER_REJECT: Bei TreeWalker schließt REJECT den kompletten Teilbaum aus; bei NodeIterator verhalten sich beide gleich.
  • whatToShow wird vor dem Filter angewendet – der Filter sieht nur Knoten der erlaubten Typen. Die Konstanten SHOW_ATTRIBUTE, SHOW_ENTITY u. a. sind veraltet und haben praktisch keine Wirkung.
  • Der Walker betritt keine Shadow-DOM-Bäume; für Web Components muss man für jede shadowRoot einen eigenen Walker erzeugen.
  • Der früher vorhandene vierte Parameter entityReferenceExpansion ist entfernt und wird ignoriert.
  • Kompatibilität: in allen modernen Browsern verfügbar (auch in IE 9+). In Node.js nur über DOM-Implementierungen wie jsdom.