Propiedades de los nodos: tipo, etiqueta y contenido
Dominar el DOM es esencial para cualquier desarrollador web. Este artículo profundiza en las propiedades principales de los nodos y cómo usarlas.
Cada nodo del árbol DOM es un objeto JavaScript, y ese objeto expone propiedades que indican qué tipo de nodo es, qué etiqueta representa y qué contenido contiene. Una vez que puedes leer estas propiedades con confianza, navegar y editar una página se vuelve mucho menos propenso a errores. Este capítulo cubre la jerarquía de clases de nodos, las propiedades de tipo y nombre (nodeType, nodeName, tagName), y las cuatro propiedades de contenido que usarás a diario (textContent, innerHTML, outerHTML y nodeValue/data), incluyendo cuándo es seguro usar cada una.
Si aún no has visto cómo se estructura el DOM como un árbol, lee primero Entendiendo los nodos del DOM.
La jerarquía de clases de nodos
Los objetos DOM no comparten todos el mismo conjunto de propiedades. Están organizados en una jerarquía de clases, donde cada clase añade capacidades a la que está por encima:
Node— la clase base. Todos los nodos (elemento, texto, comentario, documento) heredan de ella. Proporciona propiedades genéricas comonodeType,nodeName,nodeValue,parentNodeychildNodes.Element— un nodo que es una etiqueta. AñadetagName,innerHTML, atributos,childreny métodos de consulta.HTMLElement— la base de todo elemento HTML concreto. Las subclases comoHTMLInputElement,HTMLAnchorElementyHTMLTableElementañaden propiedades específicas de cada etiqueta (por ejemplo,input.value,a.href).TextyComment— nodos hoja que contienen texto. Heredan deCharacterData, que añade la propiedaddata.
Conocer esta jerarquía explica por qué un <div> tiene innerHTML pero un nodo de texto no: innerHTML vive en Element, y un nodo de texto no es un elemento. Puedes confirmar la clase de un objeto con Object.prototype.toString o el nombre del constructor:
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); // trueTipos y nombres de nodos
Tipos de nodo (nodeType)
La propiedad nodeType es un entero que identifica la categoría de un nodo. Es de solo lectura y es la forma más fiable de ramificar la lógica mientras recorres el DOM, porque los nodos de texto y comentario son fáciles de confundir con los elementos. Los valores más comunes son:
1— Nodo elemento (Node.ELEMENT_NODE): una etiqueta HTML o XML como<div>o<p>.2— Nodo atributo (Node.ATTRIBUTE_NODE): heredado; el código moderno lee atributos congetAttribute()/setAttribute()en lugar de recorrer nodos de atributo.3— Nodo de texto (Node.TEXT_NODE): el texto entre etiquetas, incluyendo espacios en blanco y saltos de línea.8— Nodo de comentario (Node.COMMENT_NODE): un comentario HTML<!-- ... -->.9— Nodo documento (Node.DOCUMENT_NODE): el propio objetodocument, la raíz del árbol.
Prefiere las constantes con nombre a los números literales: se leen mejor y nunca cambian:
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>Nombres de nodo: nodeName vs tagName
Ambas propiedades devuelven el nombre de un nodo, pero difieren en su alcance:
nodeNameexiste en todos los nodos. Para un elemento devuelve el nombre de la etiqueta; para un nodo de texto devuelve"#text"; para un comentario,"#comment"; para el documento,"#document".tagNameexiste solo en elementos. En un nodo que no sea elemento su valor esundefined.
En documentos HTML, ambas devuelven el nombre de la etiqueta en mayúsculas ("DIV", no "div"), independientemente de cómo hayas escrito la etiqueta:
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); // undefinedRegla general: usa tagName cuando ya sabes que estás trabajando con un elemento; usa nodeName cuando puedas estar inspeccionando cualquier tipo de nodo.
<!-- snippet: html-result -->
<div id="example"></div>
<script>
const element = document.getElementById('example');
element.innerHTML = 'nodeName: ' + element.nodeName;
</script>Contenido de los nodos
Hay cuatro propiedades para leer y escribir lo que hay "dentro" de un nodo. Elegir la correcta importa para la corrección, el rendimiento y la seguridad.
textContent — texto plano, seguro
textContent obtiene o establece el texto de un nodo y todos sus descendientes, ignorando cualquier marcado. Cuando lo lees, obtienes el texto concatenado con las etiquetas eliminadas. Cuando lo escribes, la cadena se inserta como texto literal — cualquier < o > se escapa, por lo que es la opción segura para mostrar datos no confiables:
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 — marcado dentro del elemento
innerHTML obtiene o establece el HTML entre las etiquetas de apertura y cierre de un elemento. Al establecerlo, analiza la cadena como HTML y reconstruye los hijos:
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>)Advertencia de seguridad: nunca asignes entrada no confiable a
innerHTML. Como el navegador la analiza como HTML, una cadena como<img src=x onerror=alert(1)>se convierte en un elemento real que ejecuta scripts — una vulnerabilidad clásica de cross-site-scripting (XSS). UsatextContentpara datos proporcionados por el usuario, o sanea antes de insertar.
outerHTML — el elemento incluyendo su propia etiqueta
outerHTML es como innerHTML pero incluye las etiquetas de apertura y cierre del propio elemento. Escribir en él reemplaza el elemento en sí en el DOM, lo que tiene una consecuencia sorprendente: tu variable sigue apuntando al nodo antiguo, ahora desconectado:
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 — texto dentro de nodos de texto y comentario
Para los nodos de texto y comentario (que no tienen innerHTML), usa nodeValue o su equivalente data para leer y escribir su contenido:
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); // null¿Cuál debo usar?
| Propiedad | Funciona en | Lee | ¿Analiza HTML al escribir? | ¿Segura para datos no confiables? |
|---|---|---|---|---|
textContent | cualquier nodo | texto plano de los descendientes | no | sí |
innerHTML | elementos | marcado interno | sí | no (riesgo de XSS) |
outerHTML | elementos | elemento + su etiqueta | sí (reemplaza el nodo) | no (riesgo de XSS) |
nodeValue / data | texto, comentario | el texto del nodo | no | sí |
Para más información sobre insertar y reemplazar contenido, consulta Modificando el documento.
Conclusión
Leer las propiedades de los nodos es la base de la programación DOM fiable. Usa nodeType (con las constantes Node.*) para distinguir las categorías de nodos, tagName/nodeName para identificar etiquetas, y elige una propiedad de contenido de forma deliberada: textContent para texto plano seguro, innerHTML/outerHTML cuando intencionalmente quieres analizar marcado, y nodeValue/data para nodos de texto y comentario simples. Usa textContent por defecto para cualquier dato que haya introducido el usuario.