¿Qué es el DOM? — Modelo de Objeto del Documento
Al finalizar este tema
Podrás explicar qué es el DOM y realizar las siguientes tareas básicas con JavaScript: seleccionar elementos HTML, modificar su contenido y asignar eventos.
HTML es texto, DOM son objetos
Cuando el navegador recibe un archivo HTML, no lo muestra directamente en la pantalla. En su lugar, analiza el texto HTML para crear una estructura de árbol de objetos en la memoria. Este árbol de objetos es el DOM (Modelo de Objeto del Documento).
<html>
<body>
<h1>Hola</h1>
<p>Encantado</p>
</body>
</html>document
└── html
└── body
├── h1 → "Hola"
└── p → "Encantado"Todas las etiquetas HTML, el texto y los atributos se convierten en nodos de este árbol. JavaScript puede leer, modificar y eliminar elementos HTML a través de este árbol.
Seleccionar elementos
Para manipular el DOM, primero debes seleccionar el elemento deseado.
// Seleccionar por ID (devuelve uno solo)
const title = document.getElementById('main-title');
// Seleccionar con selector CSS (primera coincidencia)
const firstCard = document.querySelector('.card');
// Seleccionar con selector CSS (todos)
const allCards = document.querySelectorAll('.card');querySelector permite utilizar selectores CSS directamente, lo que lo convierte en la opción más versátil. Las clases se seleccionan con .card, los identificadores con #main-title y las etiquetas con p.
// También es posible combinar
const activeItem = document.querySelector('ul.menu > li.active');Leer y modificar el contenido
const heading = document.querySelector('h1');
// Leer
console.log(heading.textContent); // "Hola"
console.log(heading.innerHTML); // "Hola" (incluye etiquetas HTML)
// Modificar
heading.textContent = 'Bienvenido'; // Solo cambia el texto
heading.innerHTML = '<em>Bienvenido</em>'; // Permite insertar HTMLtextContent procesa texto sin formato, mientras que innerHTML procesa el marcado HTML. Si se introduce la entrada del usuario en innerHTML, esto lo hace vulnerable a ataques XSS; por lo tanto, los datos del usuario deben procesarse mediante textContent.
Modificación de estilos y propiedades
const box = document.querySelector('.box');
// Cambiar estilo en línea
box.style.backgroundColor = '#3498db';
box.style.padding = '20px';
// Manipulación de clases CSS (recomendado)
box.classList.add('active');
box.classList.remove('hidden');
box.classList.toggle('selected');Aunque también se puede modificar directamente el estilo en línea, es más conveniente para el mantenimiento agregar o quitar clases CSS. Este enfoque sigue el principio de separar los estilos en archivos CSS y la lógica de comportamiento en JavaScript.
// Modificar atributo
const img = document.querySelector('img');
img.setAttribute('src', 'new-image.png');
img.setAttribute('alt', 'Nueva imagen');
// Atributo data
const card = document.querySelector('[data-id="42"]');
console.log(card.dataset.id); // "42"Creación y adición de elementos
// Crear nuevo elemento
const newItem = document.createElement('li');
newItem.textContent = 'Nuevo elemento';
newItem.classList.add('item');
// Añadir al elemento existente
const list = document.querySelector('ul');
list.appendChild(newItem); // Añadir al final
list.prepend(newItem); // Añadir al principio
list.insertBefore(newItem, list.children[1]); // Insertar en una posición específica// Al añadir varios elementos a la vez
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Elemento ${i}`;
fragment.appendChild(li);
}
list.appendChild(fragment); // Acceso al DOM una sola vezAl utilizar DocumentFragment, se pueden agrupar las modificaciones repetitivas del DOM y procesarlas de una sola vez. Dado que el acceso al DOM es una operación costosa, reducir su frecuencia mejora el rendimiento.
Eventos: reaccionar a las acciones del usuario
const button = document.querySelector('#submit');
button.addEventListener('click', function(event) {
console.log('Botón clickeado');
console.log(event.target); // Elemento clickeado
});addEventListener se compone de tres partes:
- Nombre del evento:
'click','input','submit','keydown', etc. - Función de devolución de llamada: función que se ejecuta cuando ocurre el evento.
- Objeto
event: información sobre el evento (qué tecla se presionó, las coordenadas del ratón, etc.).
// Reacción en tiempo real del campo de entrada
const input = document.querySelector('#search');
input.addEventListener('input', function(e) {
console.log('Entrada actual:', e.target.value);
});Delegación de eventos
En lugar de asignar un evento a cada uno de los 100 botones, puedes asignarlo una sola vez al elemento padre:
// ❌ Ineficiente — 100 oyentes
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
✅ Delegación de eventos — 1 solo oyente
document.querySelector('#list').addEventListener('click', function(e) {
if (e.target.classList.contains('item')) {
console.log('Elemento clickeado:', e.target.textContent);
}
});El evento de clic se propaga desde el elemento secundario al elemento principal. Al verificar e.target en el elemento principal, se puede identificar el elemento secundario en el que realmente se hizo clic. Una ventaja es que esto se aplica automáticamente a los elementos que se agregan dinámicamente.
Seguridad: textContent vs innerHTML
const userInput = '<script>alert("ataque")</script>';
element.innerHTML = userInput; // ❌ Peligroso — posible ataque XSS
element.textContent = userInput; // ✅ Seguro — las etiquetas se muestran como textoSi se inserta la entrada del usuario a través de innerHTML, se podrían ejecutar scripts maliciosos. Siempre use textContent para la entrada del usuario. Cuando se deba crear dinámicamente la estructura HTML, es más seguro ensamblarla con createElement.
DOM y frameworks
Al usar frameworks frontend modernos (React, Vue, Svelte), no se manipula el DOM directamente. El framework se encarga de esto mediante un DOM virtual o un compilador:
Manipulación directa del DOM:
Desarrollador → querySelector → modificación directa del DOM
Enfoque de React:
Desarrollador → cambio de estado → React modifica el DOMSin embargo, si no se comprenden los principios del DOM:
- No se podrá entender el funcionamiento de los frameworks.
- No se podrán depurar los problemas de rendimiento.
- No se podrán crear prototipos rápidos sin un framework.
Resumen clave
| Tarea | Método |
|---|---|
| Selección | querySelector(), querySelectorAll() |
| Lectura/Modificación | textContent, innerHTML |
| Estilos | classList.add/remove/toggle |
| Creación | createElement(), appendChild() |
| Eventos | addEventListener() |
| Delegación de eventos | Listener en el elemento padre + verificación con e.target |
El DOM es la interfaz principal que JavaScript utiliza para crear páginas web de forma dinámica. Aunque frameworks como React permiten no manipular el DOM directamente, comprender su funcionamiento es de gran ayuda para la depuración y la optimización.