Signatur
Beschreibung
previousNode() ist das Gegenstück zu nextNode(). Die Methode geht in Dokumentreihenfolge rückwärts durch alle Knoten unterhalb von root, die zu whatToShow passen und vom Filter mit NodeFilter.FILTER_ACCEPT angenommen werden. Sie gibt den ersten solchen Knoten zurück und setzt den Iterator auf diese Position. Gibt es davor keinen passenden Knoten mehr, liefert sie null. Die Position bleibt dann unverändert.
Ein NodeIterator merkt sich seine Position über zwei Werte: den Referenzknoten (referenceNode) und die Angabe, ob der Zeiger vor oder hinter diesem Knoten steht (pointerBeforeReferenceNode). Steht der Zeiger hinter dem Referenzknoten, zum Beispiel direkt nach einem nextNode(), gibt previousNode() genau diesen Referenzknoten noch einmal zurück. Wer nextNode() und previousNode() abwechselnd aufruft, bekommt also immer wieder denselben Knoten.
Typische Einsatzfälle sind das rückwärtige Durchsuchen eines Teilbaums, etwa nach der letzten Überschrift vor einem Element oder nach dem vorhergehenden Textknoten, und Navigation mit Vor- und Zurück-Schritten in Editoren oder Barrierefreiheits-Werkzeugen. Anders als beim TreeWalker gibt es keine Bewegung zu Eltern- oder Geschwisterknoten. Der Iterator kennt nur die flache Liste in Dokumentreihenfolge.
Rückgabewert
null, wenn es vor der aktuellen Position keinen passenden Knoten mehr gibt.Beispiele
Liste zuerst vorwärts, dann rückwärts durchlaufen
const liste = document.createElement('ul');
liste.innerHTML = '<li>A</li><li>B</li><li>C</li>';
const it = document.createNodeIterator(liste, NodeFilter.SHOW_ELEMENT);
// Bis ans Ende vorspulen
while (it.nextNode()) {}
// Rückwärts ausgeben
let node;
while ((node = it.previousNode())) {
console.log(node.nodeName, node.textContent);
}
Fallstrick: previousNode() direkt nach nextNode()
const div = document.createElement('div');
div.innerHTML = '<p>Eins</p><p>Zwei</p>';
const it = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, (n) =>
n.nodeName === 'P' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
);
console.log(it.previousNode()); // Zeiger steht am Anfang
console.log(it.nextNode().textContent); // Eins
console.log(it.nextNode().textContent); // Zwei
console.log(it.previousNode().textContent); // noch einmal Zwei!
console.log(it.previousNode().textContent); // Eins
Letzte Überschrift vor einem Element finden
document.body.innerHTML = `
<h1>Einleitung</h1>
<p>Text</p>
<h2>Installation</h2>
<p id="ziel">Hier stehen wir.</p>
`;
const vorherigeUeberschrift = (ziel) => {
const it = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT,
(n) => (/^H[1-6]$/.test(n.nodeName) || n === ziel)
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP
);
// Bis zum Zielelement vorlaufen
let n;
while ((n = it.nextNode()) && n !== ziel) {}
if (!n) return null;
it.previousNode(); // liefert zuerst das Ziel selbst
return it.previousNode(); // danach die vorherige Überschrift
};
console.log(vorherigeUeberschrift(document.getElementById('ziel'))?.textContent);
// Wichtig · Fallstricke
- Zeigerposition: Nach
nextNode()gibt der erste Aufruf vonpreviousNode()denselben Knoten zurück. Wer wirklich einen Schritt zurück will, musspreviousNode()zweimal aufrufen. - Startposition: Ein frisch erzeugter Iterator steht vor
root. Ein sofortiger Aufruf vonpreviousNode()liefert deshalbnull.rootselbst gehört zur Menge, wenn er zuwhatToShowund zum Filter passt. - FILTER_REJECT wirkt bei
NodeIteratorgenauso wieFILTER_SKIP: Nur der Knoten selbst wird übergangen, seine Nachfahren nicht. Das ist anders als beimTreeWalker. - Fehler: Ruft der Filter während seiner Ausführung wieder denselben Iterator auf, wirft die Methode eine
InvalidStateError-DOMException. Ausnahmen, die im Filter entstehen, werden an den Aufrufer weitergereicht. - Live-Verhalten: Der Iterator arbeitet auf dem echten DOM, nicht auf einer Momentaufnahme. Wird der Referenzknoten entfernt, verschiebt der Browser die Position automatisch.
- Kompatibilität: Wird seit Langem von allen modernen Browsern unterstützt.
detach()ist veraltet und tut nichts mehr.