Knoteneigenschaften: Typ, Tag und Inhalt
Das DOM meistern: Knoteneigenschaften wie nodeType, nodeName, tagName, innerHTML und textContent für die dynamische Webseitenmanipulation verstehen.
Jeder Knoten im DOM-Baum ist ein JavaScript-Objekt, das Eigenschaften bereitstellt, die angeben, welchen Typ der Knoten hat, welches Tag er repräsentiert und welchen Inhalt er enthält. Sobald Sie diese Eigenschaften sicher lesen können, wird das Navigieren und Bearbeiten einer Seite deutlich weniger fehleranfällig. Dieses Kapitel behandelt die Knotenklassenhierarchie, die Typ- und Namenseigenschaften (nodeType, nodeName, tagName) sowie die vier Inhaltseigenschaften, die Sie täglich verwenden werden (textContent, innerHTML, outerHTML und nodeValue/data) — einschließlich der Frage, wann jede davon sicher einzusetzen ist.
Falls Sie noch nicht gesehen haben, wie das DOM als Baum aufgebaut ist, lesen Sie zuerst Understanding the DOM Nodes.
Die Knotenklassenhierarchie
DOM-Objekte teilen nicht alle dieselben Eigenschaften. Sie sind in einer Klassenhierarchie angeordnet, bei der jede Klasse der darüber liegenden weitere Fähigkeiten hinzufügt:
Node— die Basisklasse. Jeder Knoten (Element, Text, Kommentar, Dokument) erbt von ihr. Sie stellt generische Eigenschaften wienodeType,nodeName,nodeValue,parentNodeundchildNodesbereit.Element— ein Knoten, der ein Tag darstellt. FügttagName,innerHTML, Attribute,childrenund Abfragemethoden hinzu.HTMLElement— die Basis für jedes konkrete HTML-Element. Unterklassen wieHTMLInputElement,HTMLAnchorElementundHTMLTableElementfügen tag-spezifische Eigenschaften hinzu (z. B.input.value,a.href).TextundComment— Blattknoten, die Text enthalten. Sie erben vonCharacterData, das die Eigenschaftdatahinzufügt.
Diese Hierarchie erklärt, warum ein <div> über innerHTML verfügt, ein Textknoten jedoch nicht: innerHTML gehört zu Element, und ein Textknoten ist kein Element. Sie können die Klasse eines Objekts mit Object.prototype.toString oder dem Konstruktornamen bestätigen:
const div = document.createElement('div');
console.log(div.constructor.name); // "HTMLDivElement"
console.log(div instanceof HTMLElement); // true
console.log(div instanceof Element); // true
console.log(div instanceof Node); // trueKnotentypen und -namen
Knotentypen (nodeType)
Die Eigenschaft nodeType ist eine ganze Zahl, die die Kategorie eines Knotens identifiziert. Sie ist schreibgeschützt und die zuverlässigste Methode, Ihre Logik beim Traversieren des DOM zu verzweigen, da Text- und Kommentarknoten leicht mit Elementen verwechselt werden können. Die häufigsten Werte sind:
1— Elementknoten (Node.ELEMENT_NODE): ein HTML- oder XML-Tag wie<div>oder<p>.2— Attributknoten (Node.ATTRIBUTE_NODE): veraltet; moderner Code liest Attribute mitgetAttribute()/setAttribute()statt durch das Durchlaufen von Attributknoten.3— Textknoten (Node.TEXT_NODE): der Text zwischen Tags, einschließlich Leerzeichen und Zeilenumbrüchen.8— Kommentarknoten (Node.COMMENT_NODE): ein HTML-<!-- ... -->-Kommentar.9— Dokumentknoten (Node.DOCUMENT_NODE): dasdocument-Objekt selbst, die Wurzel des Baums.
Bevorzugen Sie die benannten Konstanten gegenüber den rohen Zahlen — sie sind lesbarer und ändern sich nie:
const div = document.createElement('div');
div.textContent = 'Hello';
console.log(div.nodeType); // 1
console.log(div.nodeType === Node.ELEMENT_NODE); // true
const textNode = div.firstChild;
console.log(textNode.nodeType === Node.TEXT_NODE); // true<!-- snippet: html-result -->
<div id="example">Example node</div>
<script>
const node = document.getElementById("example");
node.innerHTML = 'Node type is: ' + node.nodeType;
</script>Knotennamen: nodeName vs tagName
Beide Eigenschaften geben den Namen eines Knotens zurück, unterscheiden sich jedoch in ihrem Geltungsbereich:
nodeNameist auf jedem Knoten vorhanden. Für ein Element gibt es den Tag-Namen zurück; für einen Textknoten gibt es"#text"zurück; für einen Kommentar"#comment"; für das Dokument"#document".tagNameist nur auf Elementen vorhanden. Bei einem Nicht-Element-Knoten ist esundefined.
Bei HTML-Dokumenten geben beide den Tag-Namen in Großbuchstaben zurück ("DIV", nicht "div"), unabhängig davon, wie Sie das Tag geschrieben haben:
const div = document.createElement('div');
console.log(div.nodeName); // "DIV"
console.log(div.tagName); // "DIV"
const textNode = document.createTextNode('hi');
console.log(textNode.nodeName); // "#text"
console.log(textNode.tagName); // undefinedFaustregel: Verwenden Sie tagName, wenn Sie bereits wissen, dass Sie es mit einem Element zu tun haben; verwenden Sie nodeName, wenn Sie möglicherweise einen beliebigen Knotentyp untersuchen.
<!-- snippet: html-result -->
<div id="example"></div>
<script>
const element = document.getElementById('example');
element.innerHTML = 'nodeName: ' + element.nodeName;
</script>Knoteninhalt
Es gibt vier Eigenschaften zum Lesen und Schreiben dessen, was sich "innerhalb" eines Knotens befindet. Die Wahl der richtigen ist wichtig für Korrektheit, Leistung und Sicherheit.
textContent — reiner Text, sicher
textContent liest oder setzt den Text eines Knotens und all seiner Nachkommen, wobei jegliches Markup ignoriert wird. Wenn Sie ihn lesen, erhalten Sie den verketteten Text mit entfernten Tags. Wenn Sie ihn schreiben, wird der string als Literaltext eingefügt — jedes < oder > wird escaped, sodass dies die sichere Wahl für die Anzeige nicht vertrauenswürdiger Daten ist:
const div = document.createElement('div');
div.innerHTML = '<b>Hi</b> there';
console.log(div.textContent); // "Hi there" (tags stripped)
div.textContent = '<script>alert(1)<\/script>';
console.log(div.textContent); // "<script>alert(1)</script>" (inert text, not executed)<!-- snippet: html-result -->
<div id="example"></div>
<script>
const element = document.getElementById('example');
element.textContent = 'Updated text content';
</script>innerHTML — Markup innerhalb des Elements
innerHTML liest oder setzt das HTML zwischen den öffnenden und schließenden Tags eines Elements. Das Setzen parst den string als HTML und erstellt die Kindknoten neu:
const div = document.createElement('div');
div.innerHTML = '<p>Para <span>one</span></p>';
console.log(div.innerHTML); // "<p>Para <span>one</span></p>"
console.log(div.children.length); // 1 (the <p>)Sicherheitswarnung: Weisen Sie
innerHTMLniemals nicht vertrauenswürdige Eingaben zu. Da der Browser sie als HTML parst, wird ein string wie<img src=x onerror=alert(1)>zu einem echten, skriptausführenden Element — ein klassisches Cross-Site-Scripting (XSS)-Loch. Verwenden SietextContentfür benutzerseitig eingegebene Daten oder bereinigen Sie diese vor dem Einfügen.
outerHTML — das Element einschließlich seines eigenen Tags
outerHTML ist wie innerHTML, schließt aber die eigenen öffnenden und schließenden Tags des Elements ein. Beim Schreiben ersetzt es das Element selbst im DOM, was eine überraschende Konsequenz hat — Ihre Variable zeigt weiterhin auf den alten, nun abgetrennten Knoten:
const div = document.createElement('div');
div.id = 'box';
div.innerHTML = 'content';
console.log(div.outerHTML); // '<div id="box">content</div>'
// Setting outerHTML replaces the node; `div` is now stale.nodeValue / data — Text innerhalb von Text- und Kommentarknoten
Für Text- und Kommentarknoten (die kein innerHTML haben) verwenden Sie nodeValue oder das gleichwertige data, um deren Inhalt zu lesen und zu schreiben:
const text = document.createTextNode('original');
console.log(text.nodeValue); // "original"
console.log(text.data); // "original"
text.data = 'changed';
console.log(text.nodeValue); // "changed"
// On an element node, nodeValue is null.
const div = document.createElement('div');
console.log(div.nodeValue); // nullWelche sollte ich verwenden?
| Eigenschaft | Funktioniert auf | Liest | Schreiben parst HTML? | Sicher für nicht vertrauenswürdige Eingaben |
|---|---|---|---|---|
textContent | jedem Knoten | reiner Text der Nachkommen | nein | ja |
innerHTML | Elementen | inneres Markup | ja | nein (XSS-Risiko) |
outerHTML | Elementen | Element + sein Tag | ja (ersetzt Knoten) | nein (XSS-Risiko) |
nodeValue / data | Text, Kommentar | der Text des Knotens | nein | ja |
Weitere Informationen zum Einfügen und Ersetzen von Inhalten finden Sie unter Modifying the Document.
Fazit
Das Lesen von Knoteneigenschaften ist die Grundlage zuverlässiger DOM-Skripterstellung. Verwenden Sie nodeType (mit den Node.*-Konstanten), um Knotenkategorien zu unterscheiden, tagName/nodeName zur Identifizierung von Tags, und wählen Sie eine Inhaltseigenschaft bewusst aus: textContent für sicheren reinen Text, innerHTML/outerHTML wenn Sie bewusst Markup parsen möchten, und nodeValue/data für reine Text- und Kommentarknoten. Verwenden Sie standardmäßig textContent für alles, was ein Benutzer eingegeben hat.