Signatur
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
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);
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'));
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}`);
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);
// Wichtig · Fallstricke
- Der Wurzelknoten selbst wird von
nextNode()nicht zurückgegeben – der erste Aufruf liefert den ersten passenden Nachfahren. Sollrootmitgeprüft werden, muss manwalker.currentNodevor 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_SKIPvs.FILTER_REJECT: BeiTreeWalkerschließtREJECTden kompletten Teilbaum aus; beiNodeIteratorverhalten sich beide gleich.whatToShowwird vor dem Filter angewendet – der Filter sieht nur Knoten der erlaubten Typen. Die KonstantenSHOW_ATTRIBUTE,SHOW_ENTITYu. 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
shadowRooteinen eigenen Walker erzeugen. - Der früher vorhandene vierte Parameter
entityReferenceExpansionist 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.