Proprietà dei nodi: tipo, tag e contenuto
Padroneggiare il DOM è fondamentale per ogni sviluppatore web. Questo articolo esplora le proprietà principali dei nodi: tipo, tag e contenuto.
Ogni nodo nell'albero DOM è un object JavaScript, e quell'object espone proprietà che indicano che tipo di nodo è, quale tag rappresenta e quale contenuto contiene. Una volta che sai leggere queste proprietà con sicurezza, navigare e modificare una pagina diventa molto meno soggetto a errori. Questo capitolo tratta la gerarchia di classi dei nodi, le proprietà di tipo e nome (nodeType, nodeName, tagName) e le quattro proprietà di contenuto che utilizzerai quotidianamente (textContent, innerHTML, outerHTML e nodeValue/data) — incluso quando ciascuna è sicura da usare.
Se non hai ancora visto come il DOM è strutturato come albero, leggi prima Capire i nodi del DOM.
La gerarchia di classi dei nodi
Gli object DOM non condividono tutti lo stesso insieme di proprietà. Sono organizzati in una gerarchia di classi, in cui ogni classe aggiunge funzionalità a quella superiore:
Node— la classe base. Ogni nodo (elemento, testo, commento, documento) eredita da essa. Fornisce proprietà generiche comenodeType,nodeName,nodeValue,parentNodeechildNodes.Element— un nodo che è un tag. AggiungetagName,innerHTML, attributi,childrene metodi di ricerca.HTMLElement— la base per ogni elemento HTML concreto. Sottoclassi comeHTMLInputElement,HTMLAnchorElementeHTMLTableElementaggiungono proprietà specifiche del tag (ad es.input.value,a.href).TexteComment— nodi foglia che contengono testo. Ereditano daCharacterData, che aggiunge la proprietàdata.
Conoscere questa gerarchia spiega perché un <div> ha innerHTML ma un nodo di testo no: innerHTML appartiene a Element, e un nodo di testo non è un elemento. Puoi verificare la classe di un object con Object.prototype.toString o il nome del costruttore:
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); // trueTipi e nomi dei nodi
Tipi di nodi (nodeType)
La proprietà nodeType è un intero che identifica la categoria di un nodo. È di sola lettura ed è il modo più affidabile per gestire la logica durante l'attraversamento del DOM, perché i nodi di testo e i nodi commento si confondono facilmente con gli elementi. I valori più comuni sono:
1— Nodo elemento (Node.ELEMENT_NODE): un tag HTML o XML come<div>o<p>.2— Nodo attributo (Node.ATTRIBUTE_NODE): legacy; il codice moderno legge gli attributi congetAttribute()/setAttribute()invece di navigare i nodi attributo.3— Nodo testo (Node.TEXT_NODE): il testo tra i tag, inclusi spazi bianchi e interruzioni di riga.8— Nodo commento (Node.COMMENT_NODE): un commento HTML<!-- ... -->.9— Nodo documento (Node.DOCUMENT_NODE): l'objectdocumentstesso, la radice dell'albero.
Preferisci le costanti con nome ai numeri grezzi — sono più leggibili e non cambiano mai:
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>Nomi dei nodi: nodeName vs tagName
Entrambe le proprietà restituiscono il nome di un nodo, ma differiscono per ambito:
nodeNameesiste su ogni nodo. Per un elemento restituisce il nome del tag; per un nodo di testo restituisce"#text"; per un commento,"#comment"; per il documento,"#document".tagNameesiste solo sugli elementi. Su un nodo non-elemento valeundefined.
Per i documenti HTML, entrambe restituiscono il nome del tag in maiuscolo ("DIV", non "div"), indipendentemente da come hai scritto il tag:
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); // undefinedRegola pratica: usa tagName quando sai già di avere a che fare con un elemento; usa nodeName quando potresti ispezionare qualsiasi tipo di nodo.
<!-- snippet: html-result -->
<div id="example"></div>
<script>
const element = document.getElementById('example');
element.innerHTML = 'nodeName: ' + element.nodeName;
</script>Contenuto dei nodi
Esistono quattro proprietà per leggere e scrivere ciò che si trova "all'interno" di un nodo. Scegliere quella giusta è importante per la correttezza, le prestazioni e la sicurezza.
textContent — testo semplice, sicuro
textContent ottiene o imposta il testo di un nodo e di tutti i suoi discendenti, ignorando qualsiasi markup. Quando lo leggi, ottieni il testo concatenato con i tag rimossi. Quando lo scrivi, la string viene inserita come testo letterale — qualsiasi < o > viene escapato, quindi è la scelta sicura per visualizzare dati non attendibili:
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 all'interno dell'elemento
innerHTML ottiene o imposta l'HTML tra il tag di apertura e di chiusura di un elemento. Impostandolo si analizza la string come HTML e si ricostruiscono i figli:
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>)Avviso di sicurezza: non assegnare mai input non attendibile a
innerHTML. Poiché il browser lo analizza come HTML, una string come<img src=x onerror=alert(1)>diventa un elemento reale ed eseguibile — un classico attacco cross-site-scripting (XSS). UsatextContentper i dati forniti dall'utente, oppure sanifica prima di inserire.
outerHTML — l'elemento incluso il suo tag
outerHTML è come innerHTML ma include i tag di apertura e chiusura dell'elemento stesso. Scrivervi sopra sostituisce l'elemento nel DOM, con una conseguenza inaspettata — la tua variabile punta ancora al vecchio nodo, ora staccato:
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 — testo all'interno di nodi di testo e commenti
Per i nodi di testo e commento (che non hanno innerHTML), usa nodeValue o il suo equivalente data per leggere e scrivere il loro contenuto:
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); // nullQuale usare?
| Proprietà | Funziona su | Legge | La scrittura analizza HTML? | Sicura per input non attendibili |
|---|---|---|---|---|
textContent | qualsiasi nodo | testo semplice dei discendenti | no | sì |
innerHTML | elementi | markup interno | sì | no (rischio XSS) |
outerHTML | elementi | elemento + il suo tag | sì (sostituisce il nodo) | no (rischio XSS) |
nodeValue / data | testo, commento | il testo del nodo | no | sì |
Per ulteriori informazioni sull'inserimento e la sostituzione di contenuto, consulta Modificare il documento.
Conclusione
Leggere le proprietà dei nodi è il fondamento di uno scripting DOM affidabile. Usa nodeType (con le costanti Node.*) per distinguere le categorie di nodi, tagName/nodeName per identificare i tag, e scegli deliberatamente una proprietà di contenuto: textContent per testo semplice sicuro, innerHTML/outerHTML quando vuoi intenzionalmente analizzare markup, e nodeValue/data per nodi di testo e commento puri. Usa textContent come impostazione predefinita per qualsiasi dato inserito dall'utente.