Signatur
Beschreibung
Die Methode normalize() des Node-Interfaces räumt die Textknoten im Unterbaum eines Knotens auf. Danach gilt: Es gibt keine leeren Textknoten mehr, und es liegen keine zwei Textknoten direkt nebeneinander. Benachbarte Textknoten werden zu einem einzigen Knoten zusammengeführt, dessen data die aneinandergehängten Inhalte enthält.
Solche zersplitterten Textknoten entstehen vor allem bei DOM-Manipulationen per Skript, z. B. durch mehrfaches appendChild(document.createTextNode(...)), durch Text.prototype.splitText() oder durch Bibliotheken für Syntax-Hervorhebung und Suchtreffer-Markierung, die <mark>-Elemente einfügen und wieder entfernen. Der HTML-Parser selbst erzeugt normalerweise keine benachbarten Textknoten.
Nützlich ist normalize() immer dann, wenn Code sich auf die Struktur der Textknoten verlässt, etwa bei childNodes-Vergleichen, bei der Arbeit mit Range- und Selection-Offsets oder bei TreeWalker-Durchläufen. Die sichtbare Darstellung ändert sich durch den Aufruf nicht, nur die interne Knotenstruktur.
Beispiele
Benachbarte Textknoten zusammenführen
const wrapper = document.createElement('div');
wrapper.appendChild(document.createTextNode('Teil 1 '));
wrapper.appendChild(document.createTextNode('Teil 2 '));
wrapper.appendChild(document.createTextNode(''));
wrapper.appendChild(document.createTextNode('Teil 3'));
console.log(wrapper.childNodes.length);
wrapper.normalize();
console.log(wrapper.childNodes.length);
console.log(wrapper.firstChild.data);
Aufräumen nach dem Entfernen von Suchtreffer-Markierungen
// Entfernt alle <mark>-Elemente und stellt einen sauberen Textknoten wieder her
const unhighlight = (container) => {
container.querySelectorAll('mark').forEach((mark) => {
mark.replaceWith(...mark.childNodes);
});
container.normalize();
};
const p = document.createElement('p');
p.innerHTML = 'Ein <mark>markiertes</mark> Wort';
console.log(p.childNodes.length);
unhighlight(p);
console.log(p.childNodes.length, JSON.stringify(p.firstChild.data));
Nach splitText() wieder vereinen
const p = document.createElement('p');
p.textContent = 'HalloWelt';
const rest = p.firstChild.splitText(5);
console.log(p.childNodes.length, rest.data);
p.normalize();
console.log(p.childNodes.length, p.textContent);
console.log(rest.isConnected);
// Wichtig · Fallstricke
- Referenzen können ungültig werden: Beim Zusammenführen bleibt nur der erste Textknoten erhalten, die übrigen werden aus dem DOM entfernt. Gespeicherte Variablen auf diese Knoten zeigen danach auf abgehängte Knoten (
isConnected === false). - Range/Selection: Laut DOM-Standard werden die Grenzen bestehender
Range-Objekte angepasst. Eigene gespeicherte Offsets (Knoten + Index) werden aber nicht automatisch nachgeführt. - Nur Text-Knoten sind betroffen.
CDATASection, Kommentare und Leerraum zwischen Elementen (nicht leere Whitespace-Textknoten) bleiben erhalten.normalize()entfernt also keine Leerzeichen und ist nicht dasselbe wieString.prototype.normalize()(Unicode-Normalisierung). - Performance: Der Aufruf durchläuft den gesamten Unterbaum. Rufen Sie ihn deshalb auf dem kleinstmöglichen Container auf und nicht bei jeder Änderung auf
document. Jeder Eingriff kann außerdemMutationObserver-Einträge auslösen. - Kompatibilität: wird seit Langem von allen Browsern unterstützt. Ältere Versionen von Internet Explorer hatten Fehler im Umgang mit leeren Textknoten.