Signatur
Beschreibung
Die schreibgeschützte Eigenschaft previousSibling eines MutationRecord gibt den Knoten zurück, der im target unmittelbar vor den Knoten stand, die in addedNodes oder removedNodes aufgeführt sind. So lässt sich genau feststellen, an welcher Stelle Knoten eingefügt oder entfernt wurden.
Einen Wert hat die Eigenschaft nur bei Datensätzen vom Typ "childList". Bei "attributes"- und "characterData"-Mutationen ist sie immer null. Auch bei childList-Mutationen ist sie null, wenn die geänderten Knoten am Anfang der Kindliste standen bzw. eingefügt wurden, es also keinen Vorgänger gibt.
Zusammen mit nextSibling beschreibt previousSibling die Position der Änderung eindeutig. Das hilft, wenn man DOM-Änderungen nachvollziehen, protokollieren oder in einer anderen Struktur spiegeln will, etwa beim Synchronisieren eines virtuellen DOMs, bei Undo/Redo-Funktionen oder bei Werkzeugen zur Aufzeichnung von Sitzungen.
Der Wert zeigt den Stand zum Zeitpunkt der Mutation. Wurde das DOM danach weiter verändert, kann der Knoten inzwischen woanders stehen oder schon entfernt sein.
Rückgabewert
null, wenn es keinen Vorgänger gibt oder der Datensatz nicht vom Typ childList ist.Beispiele
Einfügeposition eines neuen Listeneintrags ermitteln
const list = document.createElement('ul');
list.innerHTML = '<li id="a">A</li><li id="b">B</li>';
document.body.append(list);
const observer = new MutationObserver((records) => {
for (const record of records) {
if (record.type !== 'childList') continue;
const prev = record.previousSibling;
console.log('Vorgänger:', prev ? prev.id : null);
console.log('Neu:', [...record.addedNodes].map((n) => n.id));
}
});
observer.observe(list, { childList: true });
// Neues Element hinter #a einfügen
const c = document.createElement('li');
c.id = 'c';
c.textContent = 'C';
list.insertBefore(c, list.querySelector('#b'));
null beim Einfügen am Anfang
const box = document.createElement('div');
box.append(document.createElement('span'));
document.body.append(box);
new MutationObserver(([record]) => {
console.log(record.previousSibling); // kein Vorgänger
console.log(record.nextSibling.nodeName);
}).observe(box, { childList: true });
box.prepend(document.createElement('strong'));
Entfernte Knoten samt Position protokollieren (z. B. für Undo)
const editor = document.querySelector('#editor') ?? document.body;
const undoStack = [];
const observer = new MutationObserver((records) => {
for (const { type, target, removedNodes, previousSibling, nextSibling } of records) {
if (type !== 'childList' || removedNodes.length === 0) continue;
undoStack.push({ parent: target, nodes: [...removedNodes], previousSibling, nextSibling });
}
});
observer.observe(editor, { childList: true, subtree: true });
// Letzte Entfernung rückgängig machen
const undo = () => {
const entry = undoStack.pop();
if (!entry) return;
observer.disconnect(); // eigene Änderung nicht erneut aufzeichnen
const ref = entry.nextSibling ?? (entry.previousSibling ? entry.previousSibling.nextSibling : entry.parent.firstChild);
for (const node of entry.nodes) entry.parent.insertBefore(node, ref);
observer.observe(editor, { childList: true, subtree: true });
};
// Wichtig · Fallstricke
- Text- und Kommentarknoten:
previousSiblingist ein beliebigerNode, kein Element. Leerzeichen und Zeilenumbrüche im HTML ergeben oft Textknoten als Vorgänger. Prüfe darumnodeTypeoder suche selbst nach dem nächsten Element (z. B. mitpreviousElementSiblingam aktuellen Knoten). - Nur bei
childList: Bei Attribut- und Textänderungen ist der Wert immernull. Deshalb zuerstrecord.typeprüfen. - Zusammengefasste Datensätze: Bei Operationen wie
innerHTML = …oderreplaceChildren()entsteht oft nur ein Datensatz mit vielen Knoten.previousSiblinggilt dann für den ganzen Block, nicht für jeden einzelnen Knoten. - Momentaufnahme: Da Callbacks asynchron als Mikrotask laufen, kann sich das DOM seit der Mutation bereits geändert haben. Der Vorgänger ist dann womöglich nicht mehr im Dokument.
- In allen modernen Browsern unterstützt. Vorgänger waren die veralteten Mutation Events (z. B.
DOMNodeInserted), die nicht mehr verwendet werden sollten.