Definición de JavaScript
JavaScript es un lenguaje de programación interpretado/compilado Just-In-Time (JIT), dinámico, multiparadigma (soporta imperativo, orientado a objetos y funcional) y orientado a eventos, diseñado originalmente para el navegador. Permite manipular el DOM, gestionar eventos de usuario, consumir APIs (HTTP/JSON), almacenar datos localmente y crear interfaces interactivas. También se ejecuta fuera del navegador en entornos como Node.js.
Especificaciones
El estándar que define el lenguaje se llama ECMAScript (ECMA-262), mantenido por el comité TC39. Las nuevas características pasan por un proceso de propuestas con etapas (stages 0–4); solo las de Stage 4 se integran al estándar. Los motores (V8, SpiderMonkey, JavaScriptCore, Chakra) implementan estas especificaciones.
Funcionamiento básico de JavaScript
En el navegador, JavaScript corre en un hilo principal con pila de llamadas, heap y un event loop que coordina macrotareas (Timers, I/O, eventos) y microtareas (promesas). Es single-threaded por defecto (aunque existen Web Workers). El motor compila JIT para optimizar el rendimiento a partir de la ejecución real.
Incluir JavaScript en un archivo HTML
Se usa la etiqueta <script>
:
- Interno (inline):
<script> console.log('Hola'); </script>
- Externo:
<script src="app.js"></script>
- Carga controlada:
defer
: descarga en paralelo y ejecuta tras el parseo del HTML, respetando el orden.async
: descarga en paralelo y ejecuta en cuanto carga, sin garantizar el orden.type="module"
: activa módulos ES; por defecto se comporta como defer y permiteimport/export
.
Etiqueta <noscript></noscript>
Muestra contenido alternativo cuando JavaScript está deshabilitado o no soportado. El contenido dentro de <noscript>
se ignora si JS está activo. Útil para mensajes de accesibilidad o rutas de “gracia degradada”.
Definición de Script
“Script” es un conjunto de instrucciones escrito en un lenguaje interpretado (como JavaScript) que el motor ejecuta para automatizar tareas, manipular datos o controlar la interfaz, generalmente sin un proceso de compilación separado por parte del desarrollador.
Definición de sentencias
Una sentencia (statement) es una unidad completa de ejecución: declaración (let x = 1;
), control de flujo (if
, for
, while
), expresión con efectos (x++;
), return
, etc. Pueden terminar con punto y coma; JavaScript aplica Inserción Automática de Puntos y Coma (ASI) con reglas específicas.
Palabras Reservadas del Lenguaje
Son identificadores prohibidos para variables/funciones porque tienen significado sintáctico: break
, case
, catch
, class
, const
, continue
, debugger
, default
, delete
, do
, else
, export
, extends
, finally
, for
, function
, if
, import
, in
, instanceof
, let
, new
, return
, super
, switch
, this
, throw
, try
, typeof
, var
, void
, while
, with
, yield
, await
(en contextos donde aplica). También hay futuras/reservadas en modo estricto.
Comentarios JavaScript
- Una línea:
// comentario
- Bloque:
/* comentario */
Se usan para documentar, desactivar temporalmente código o aclarar intenciones. Los comentarios no se ejecutan.
Sintaxis del Lenguaje
JavaScript es sensible a mayúsculas y minúsculas, los identificadores pueden usar Unicode, el código se compone de tokens (palabras clave, literales, operadores, delimitadores). El espaciado generalmente no afecta, salvo en casos puntuales (como la ASI). Las expresiones producen valores; las sentencias ejecutan acciones.
Posibilidades y limitaciones
Posibilidades (en navegador): manipular el DOM, gestionar eventos, consumir APIs vía fetch
, almacenamiento local (localStorage
, IndexedDB
), gráficos (Canvas
, WebGL
), audio/video, WebSockets, Service Workers, etc.
Limitaciones: sin acceso directo al sistema de archivos del cliente (más allá de APIs mediadas/permiso), política de mismo origen (SOP) restringe solicitudes, dependiente del hilo principal (bloqueos si hay tareas pesadas), sin ejecución de binarios nativos por seguridad.
JavaScript y los navegadores
JavaScript es el lenguaje que permite añadir interactividad a las páginas web ejecutándose dentro del navegador. Los navegadores incluyen motores de JavaScript (por ejemplo V8 en Chrome/Edge, SpiderMonkey en Firefox, JavaScriptCore en Safari) que interpretan/compilan JIT el código y lo ejecutan sobre el event loop del entorno del navegador.
En el contexto del navegador hay dos colecciones importantes de objetos:
- DOM (Document Object Model): representa la página HTML (
document
, nodos, elementos), y permite leer/modificar la estructura, estilos y contenido. - BOM (Browser Object Model): objetos globales del navegador como
window
,navigator
,location
,console
.
JavaScript en el navegador está sujeto a restricciones de seguridad (p. ej. Same Origin Policy y CORS) y suele ejecutarse en el hilo principal; para tareas pesadas se usan Web Workers.
Variables
Una variable es un nombre que almacena un dato. En JavaScript existen tres formas principales de declarar variables:
var
: tiene alcance de función o global si se declara fuera; permite redeclaración; su declaración se hoistea (se mueve la declaración al inicio del ámbito, inicializada conundefined
).let
: tiene alcance de bloque ({...}
), no permite redeclaración en el mismo ámbito y sí permite reasignación.const
: también tiene alcance de bloque, no permite reasignación del identificador (la referencia es constante), aunque el contenido de un objeto o array asignado a unaconst
puede modificarse.
Reglas: nombres válidos no pueden comenzar con dígitos, no usar palabras reservadas, y distinguen entre mayúsculas y minúsculas.
Tipos de variables
JavaScript es débilmente tipado y dinámico: una variable puede contener valores de distinto tipo en tiempo de ejecución. Hay tipos primitivos y tipos por referencia.
Numéricas
El tipo Number
representa números en IEEE-754 (coma flotante de doble precisión). Existen valores especiales: NaN
(Not-a-Number), Infinity
, -Infinity
. Desde ES2020 existe BigInt
para enteros muy grandes. Para convertir cadenas a números se usan Number()
, parseInt()
, parseFloat()
. Operadores matemáticos: +
, -
, *
, /
, %
(resto), **
(potencia).
Cadenas
Las cadenas (String
) son secuencias de caracteres. Se pueden definir con comillas simples '...'
, dobles "..."
o backticks (plantillas) `...`
que permiten interpolación con ${expresión}
y multilínea. Las cadenas son inmutables (las operaciones devuelven nuevas cadenas). Hay métodos como .length
, .slice()
, .toUpperCase()
, .replace()
, etc.
Array
Los arrays son listas ordenadas indexadas desde 0
. Se definen con []
o new Array(...)
. Tienen la propiedad .length
y métodos como .push()
, .pop()
, .shift()
, .unshift()
, .slice()
, .splice()
, .map()
, .filter()
, .forEach()
. En JavaScript un array es un objeto (por eso typeof []
es 'object'
), pero tiene comportamiento especial y utilidades (como Array.isArray()
para distinguirlo).
Boléanos
El tipo Boolean
tiene dos valores: true
y false
. En control de flujo, JavaScript convierte valores a booleanos usando la lógica de truthy/falsy: false
, 0
, ''
(cadena vacía), null
, undefined
, y NaN
son falsy; el resto son truthy.
Objetos
Un objeto es una colección de pares clave: valor
. Se crean con notación literal {}
o con new Object()
. Los valores pueden ser primitivos, funciones (métodos) u otros objetos. El acceso a propiedades se hace con notación de punto obj.prop
o corchetes obj['prop']
(útil para claves dinámicas). Los objetos son mutables; JavaScript usa herencia prototípica (prototype
) para métodos y propiedades compartidas.
Operadores matemáticos
Operan sobre valores numéricos (o que se convierten a numérico): +
(suma / concatena si hay strings), -
, *
, /
, %
(resto), **
(potencia). Además existen operadores unarios como +
(convierte a número) y -
(cambia signo). Para funciones matemáticas complejas se usa el objeto Math
(Math.sqrt()
, Math.round()
, Math.random()
, etc.).
Operadores de asignación
Asignación simple =
. Operadores de asignación compuesta combinan operación y asignación: +=
, -=
, *=
, /=
, %=
, **=
(por ejemplo x += 3
equivale a x = x + 3
).
Incremento y decremento
++
y --
. Pueden usarse en prefijo (++x
) o sufijo (x++
). En prefijo incrementan/decrementan y devuelven el nuevo valor; en sufijo devuelven el valor antiguo y luego realizan el cambio.
Operadores relacionales / de comparación
Comparaciones numéricas y lexicográficas: >
, <
, >=
, <=
. Para igualdad: ==
(igualdad con coerción de tipos) y ===
(igualdad estricta sin coerción). Para desigualdad !=
y !==
. Es buena práctica usar ===
y !==
para evitar problemas de coerción.
Lógicos
Los operadores lógicos permiten combinar o invertir expresiones booleanas en JavaScript:
&&
(AND): devuelvetrue
si ambas expresiones son verdaderas.||
(OR): devuelvetrue
si al menos una expresión es verdadera.!
(NOT): invierte el valor lógico de una expresión.
Además de devolver valores booleanos, en JavaScript estos operadores aplican cortocircuito:a && b
devuelvea
si es falsy, de lo contrario devuelveb
;a || b
devuelvea
si es truthy, de lo contrario devuelveb
.
Estructuras de Control de Flujos
If, if else
Permiten ejecutar bloques de código basados en condiciones.
if (condición) { ... }
: ejecuta el bloque si la condición es verdadera.if...else
: permite un bloque alternativo si la condición es falsa.if...else if...else
: múltiples condiciones evaluadas en orden.
For
El bucle clásico for
ejecuta un bloque un número determinado de veces, con inicialización, condición y actualización:
for (let i = 0; i < 5; i++) {
console.log(i);
}
For in
for...in
recorre las propiedades enumerables de un objeto (claves).
const persona = { nombre: "Ana", edad: 30 };
for (let clave in persona) {
console.log(clave, persona[clave]);
}
Nota: no se recomienda para arrays, ya que recorre índices como cadenas y también propiedades heredadas.
Funciones útiles para Cadenas
Algunos métodos importantes del objeto String
son:
.length
: devuelve longitud..charAt(i)
,.at(i)
: devuelve carácter en posición..toUpperCase()
,.toLowerCase()
..indexOf(sub)
,.includes(sub)
..slice(inicio, fin)
,.substring(inicio, fin)
..replace(patrón, nuevo)
,.replaceAll()
..split(separador)
: convierte a array..trim()
,.trimStart()
,.trimEnd()
..startsWith()
,.endsWith()
.
Funciones útiles para Arrays
Métodos más usados:
- Mutación:
.push()
,.pop()
,.shift()
,.unshift()
,.splice()
,.sort()
,.reverse()
. - No mutan:
.slice()
,.concat()
,.map()
,.filter()
,.reduce()
,.forEach()
,.find()
,.some()
,.every()
,.includes()
. - Utilidad:
.length
.
Funciones útiles para Números
JavaScript ofrece el objeto Math
y el tipo Number
:
- Conversiones:
parseInt()
,parseFloat()
,Number()
. - Validaciones:
isNaN()
,Number.isInteger()
,Number.isFinite()
. - Operaciones:
Math.sqrt()
,Math.pow()
,Math.round()
,Math.floor()
,Math.ceil()
,Math.random()
,Math.abs()
,Math.max()
,Math.min()
.
Funciones
Definición y explicación
Una función es un bloque de código reutilizable que realiza una tarea concreta. Se define con una declaración (function nombre(...) { ... }
), con una expresión (const f = function(...) { ... }
) o como arrow function (const f = (...) => { ... }
). Las funciones son ciudadanos de primera clase en JavaScript: se pueden asignar a variables, pasar como argumentos y devolver desde otras funciones. Existen diferencias importantes entre tipos de funciones (por ejemplo, las arrow functions no tienen su propio this
ni objeto arguments
). MDN Web Docs
Ámbito de variables (scope)
El ámbito determina dónde es visible una variable:
- Global: accesible desde cualquier parte (cuando se declara en el nivel superior).
- Ámbito de función:
var
crea variables con alcance de función (o global si se declara fuera de una función). - Ámbito de bloque:
let
yconst
crean variables con alcance de bloque ({ ... }
).
Además existe el ámbito léxico (lexical scope): las funciones recuerdan el ámbito donde fueron definidas (esto es la base de los closures). También hay reglas de hoisting: declaraciones devar
y declaraciones de función se “mueven” al inicio de su ámbito;let
/const
se comportan diferente y no están inicializadas hasta su declaración. MDN Web Docs
Argumentos y valores de retorno
- Parámetros son los nombres en la definición; argumentos son los valores pasados en la llamada.
- Puedes definir valores por defecto (
function f(x = 1) {}
) y usar rest parameters (function f(...args) {}
) para capturar múltiples argumentos. - Una función devuelve un valor con
return
. Si no se usareturn
, la función devuelveundefined
.return
termina la ejecución de la función inmediatamente.
Llamadas a funciones
Se invoca una función por su nombre seguido de paréntesis: f(1, 2)
. Existen varias formas de invocar:
- Llamada normal:
fn()
- Como método:
obj.metodo()
(aquíthis
esobj
) - Con
call
/apply
para fijarthis
y pasar argumentos (fn.call(thisArg, a, b)
/fn.apply(thisArg, [a,b])
) - Con
bind
para crear una nueva función conthis
ligado:const g = fn.bind(thisArg)
- Como constructor con
new
(si la función está pensada para ello).
Las funciones pueden usarse como callbacks y retornar otras funciones (funciones de orden superior).
Objeto arguments
Dentro de funciones normales existe un objeto local llamado arguments
que contiene todos los argumentos pasados: es array-like (arguments[0]
, arguments.length
) pero no es un Array real. En código moderno se recomienda usar rest parameters (...args
) en lugar de arguments
. Nota: las arrow functions no tienen su propio arguments
. MDN Web Docs
Otras estructuras de Control
do...while
Es un bucle que ejecuta el bloque al menos una vez y luego evalúa la condición; si la condición es verdadera, repite. Sintaxis básica:
do {
// cuerpo
} while (condición);
Útil cuando la primera iteración debe ejecutarse siempre. MDN Web Docs
while
Ejecuta el bloque mientras la condición sea true
. La condición se evalúa antes de cada iteración:
while (condición) {
// cuerpo
}
Si la condición es falsa desde el inicio, el cuerpo no se ejecuta. MDN Web Docs
continue
Dentro de bucles (for
, while
, do...while
, for...of
, etc.), continue
termina la iteración actual y pasa a la siguiente. En un for
, salta al paso de actualización; en while
/do...while
vuelve a evaluar la condición. No finaliza todo el bucle (eso sería break
). MDN Web Docs
break
break
termina inmediatamente el bucle (o switch
) y transfiere la ejecución a la instrucción siguiente al bloque. Existe break
sin etiqueta (termina el bucle más interno) y break
con etiqueta (permite salir de un bloque etiquetado externo). MDN Web Docs
switch
switch (expresión) { case valor1: ... break; case valor2: ... break; default: ... }
switch
compara la expresión con cada case
y ejecuta el bloque correspondiente. Si omites break
, la ejecución cae (fall-through) al siguiente case
hasta encontrar break
o finalizar el switch
. Es útil para múltiples ramas basadas en un único valor.
DOM — Concepto
DOM (Document Object Model) es una representación en memoria de un documento HTML o XML que organiza el contenido como una estructura de objetos accesible y manipulable desde lenguajes de programación (por ejemplo JavaScript). El DOM define una API estándar (con nodos, propiedades y métodos) que permite leer, crear, modificar y eliminar elementos, atributos y texto en la página web, así como responder a eventos del usuario.
Explicación del DOM (Document Object Model)
El DOM transforma el documento (HTML/XML) en una estructura jerárquica que los scripts pueden recorrer y modificar. Cada elemento HTML se convierte en un objeto (nodo) con propiedades (por ejemplo id
, className
, style
) y métodos (por ejemplo appendChild
, getAttribute
). El DOM separa la representación lógica del documento (árbol de nodos) de su presentación visual; cuando se modifican nodos, el navegador puede recalcular estilos y realizar reflow/repaint para actualizar la vista.
Árbol de nodos
El documento se modela como un árbol donde el nodo raíz es el objeto document
(y su hijo principal suele ser document.documentElement
, es decir <html>
). Cada nodo puede tener hijos (child nodes) y padre (parent node). Este árbol incluye nodos de distintos tipos (elementos, texto, comentarios, etc.), formando una jerarquía que permite recorrer el documento hacia arriba, abajo o lateralmente (siblings).
Tipos de nodos
Entre los tipos más importantes:
- Element (ELEMENT_NODE): representa etiquetas HTML (
<div>
,<p>
, etc.). - Text (TEXT_NODE): contiene texto dentro de un elemento.
- Comment (COMMENT_NODE): representa comentarios
<!-- ... -->
. - Document (DOCUMENT_NODE): representa el documento completo (
document
). - DocumentFragment: contenedor ligero para construir subárboles sin estar en el DOM, útil para operaciones de rendimiento.
- Attr (ATTRIBUTE_NODE): representa atributos (históricamente como nodos
Attr
); hoy en día se suelen leer/escribir congetAttribute
/setAttribute
o como propiedades del elemento.
(Nota: cada tipo tiene una constante en la APINode
, p. ej.Node.ELEMENT_NODE === 1
.)
Acceso directo a los nodos
Existen múltiples formas de obtener nodos:
- Selectores modernos:
document.querySelector(selector)
(primer match),document.querySelectorAll(selector)
(todos — devuelve NodeList estático). - Métodos clásicos:
document.getElementById(id)
(elemento único),document.getElementsByClassName(clase)
(HTMLCollection vivo),document.getElementsByTagName(tag)
(HTMLCollection vivo). - Propiedades directas:
document.body
,document.documentElement
. - Navegación entre nodos:
parentNode
,parentElement
,children
,childNodes
,firstChild
,firstElementChild
,nextSibling
,nextElementSibling
,previousSibling
,previousElementSibling
.
Cómo crear y eliminar nodos
Crear nodos:
document.createElement('div')
→ crea un elemento.document.createTextNode('texto')
→ crea un nodo de texto.document.createDocumentFragment()
→ fragmento para construir en memoria.
Insertar/adjuntar:parent.appendChild(node)
— añade como último hijo (acepta solo Node).parent.insertBefore(newNode, referenceNode)
— inserta antes del nodo de referencia.parent.replaceChild(newNode, oldNode)
— reemplaza y devuelveoldNode
.element.append(nodeOrString)
— moderno: admite nodos y cadenas.
Eliminar:parent.removeChild(child)
— elimina y devuelvechild
.element.remove()
— elimina el elemento mismo del DOM (más directo).
Clonación:node.cloneNode(true)
— copia profunda (incluye hijos),cloneNode(false)
— copia superficial.
Acceso directo a los atributos
- API basada en atributos:
element.getAttribute(name)
,element.setAttribute(name, value)
,element.removeAttribute(name)
. - Propiedades del elemento: muchos atributos tienen propiedades reflectadas (por ejemplo
input.value
,img.src
,a.href
) que muestran y pueden cambiar el estado actual; nota importante: la propiedad puede diferir del atributo original (por ejemplo lavalue
de un<input>
refleja el valor actual del control, mientras quegetAttribute('value')
devuelve el valor inicial marcado en el HTML). element.attributes
devuelve un objeto tipo NamedNodeMap con pares nombre/valor (menos usado directamente).element.dataset
permite acceso conveniente a atributosdata-*
mediante propiedades camelCase (p. ej.data-user-id
→element.dataset.userId
).- Para clases existe
element.className
(cadena) yelement.classList
(interfaz con.add()
,.remove()
,.toggle()
,.contains()
).
Evento
Un evento es una señal que indica que ha ocurrido algo en la página o en el entorno (por ejemplo: un clic, el envío de un formulario, la carga del documento, pulsación de tecla, cambio de tamaño de ventana). Los eventos permiten al código JavaScript responder a la interacción del usuario y a cambios en el entorno.
Un manejador de eventos (o handler) es la función que se ejecuta cuando se produce un evento. Un listener o observador es el mecanismo que “escucha” eventos y llama al manejador cuando corresponda.
El objeto evento (por ejemplo Event
, MouseEvent
, KeyboardEvent
) contiene información sobre el suceso: tipo (type
), objetivo (target
), la fase de propagación (eventPhase
), coordenadas del ratón (clientX
, clientY
), teclas modificadoras (ctrlKey
, shiftKey
), si puede ser cancelado (cancelable
), entre otras propiedades y métodos como preventDefault()
y stopPropagation()
.
Acción por defecto (default action): muchos eventos llevan asociado un comportamiento por defecto (por ejemplo, submit
envía datos, a
con href
navega). event.preventDefault()
cancela esa acción predeterminada cuando el evento es cancelable.
Delegación de eventos: patrón que consiste en escuchar un evento en un ancestro común y, mediante event.target
, manejar eventos de muchos elementos hijos sin asignar escuchadores a cada uno.
Eventos y propagación
Cuando ocurre un evento en el DOM, éste sigue tres fases:
- Captura (capturing phase): el evento baja desde el
document
hacia el nodo objetivo pasando por los ancestros. - Fase objetivo (target phase): el evento llega al nodo objetivo.
- Burbujeo (bubbling phase): el evento sube desde el objetivo hacia el
document
a través de los ancestros.
addEventListener
permite especificar si el listener actúa en la fase de captura (capture: true
) o en la de burbujeo (capture: false
, por defecto). event.stopPropagation()
impide que el evento continúe propagándose; event.stopImmediatePropagation()
además evita que otros listeners en el mismo nodo se ejecuten. event.preventDefault()
impide la acción predeterminada.
Tipos de modelos de eventos
- Modelo DOM Level 0 (propiedades onX): asignación directa a propiedades como
element.onclick = handler
. Simple pero permite solo un handler por evento por propiedad (último asignado sobrescribe). - Modelo DOM Level 2 (addEventListener):
element.addEventListener(type, handler, options)
agrega múltiples listeners, permite control de fase (capture
) y opciones (once
,passive
,signal
), y es el método moderno recomendado. - Modelos antiguos/propietarios:
element.attachEvent
era usado por versiones antiguas de Internet Explorer (legacy) con diferencias de comportamiento (no estándar). Hoy en día se evita.
Opciones útiles de addEventListener
:
capture
(boolean): escuchar en la fase de captura.once
(boolean): el listener se ejecuta una vez y se elimina.passive
(boolean): indica que el listener no llamarápreventDefault()
; útil para mejorar rendimiento en eventos de scroll/touch.signal
: permite cancelar listeners medianteAbortController
.
Modelos básicos de eventos
Eventos del mouse
Eventos principales: click
, dblclick
, mousedown
, mouseup
, mousemove
, mouseenter
, mouseleave
, mouseover
, mouseout
, contextmenu
.
Propiedades frecuentes del objeto MouseEvent
: clientX
, clientY
, pageX
, pageY
, button
(qué botón), buttons
(estado), ctrlKey
, shiftKey
, altKey
, metaKey
.
Diferencia importante: mouseenter
/mouseleave
no burbujean; mouseover
/mouseout
sí burbujean y disparan incluso al entrar/salir hacia nodos hijos.
Eventos de la ventana
Eventos globales del objeto window
o document
como: DOMContentLoaded
(DOM parseado), load
(recursos cargados), beforeunload
(navegación/recarga inminente — con limitaciones modernas), unload
, resize
, scroll
, online
/offline
.DOMContentLoaded
es útil para ejecutar scripts cuando la estructura DOM está lista sin esperar imágenes; load
espera a todos los recursos.
Eventos de formularios
Eventos típicos: submit
(envío de formulario), reset
(restablecer), input
(cada cambio en un control de entrada), change
(cuando un control pierde el foco o cambia su valor final), focus
y blur
(ganar/perder foco), focusin
/focusout
(versiones que sí burbujean).
Para impedir que un formulario envíe: manejar submit
y usar event.preventDefault()
.
Eventos del teclado
Eventos: keydown
(tecla presionada — repetición posible), keyup
(tecla soltada), keypress
(históricamente para caracteres; está obsoleto en muchos contextos).
Propiedades relevantes: key
(valor imprimible o nombre, p. ej. ‘a’, ‘Enter’, ‘ArrowUp’), code
(código físico de la tecla), repeat
(si la tecla se mantiene pulsada), ctrlKey
, shiftKey
, altKey
, metaKey
.
Usar keydown
para capturar controles y keyup
para detectar liberación; cuidado con accesibilidad y con anular comportamiento esperado sin necesidad.
Buenas prácticas y consideraciones
- Preferir
addEventListener
sobreon*
para permitir múltiples listeners y mayor control. - Usar
passive: true
para listeners descroll
ytouchstart
cuando no se usapreventDefault()
para mejorar rendimiento. - Delegar eventos cuando se manejan muchos elementos dinámicos.
- Evitar listeners pesados en el hilo principal (usar
requestAnimationFrame
para animaciones oWeb Worker
para cálculos intensos). - No confiar en
beforeunload
para lógica crítica; navegadores limitan su uso por razones de UX/seguridad. - Siempre limpiar listeners innecesarios (
removeEventListener
), o usaronce: true
cuando aplicable.
Manejo de eventos como atributos (inline)
El manejo de eventos por atributos significa escribir el manejador directamente en el HTML, por ejemplo:
<button onclick="miFuncion()">Clic</button>
Ventajas: es directo y fácil para demostraciones rápidas.
Desventajas: mezcla marcado (HTML) y comportamiento (JS), hace dependientes las funciones del ámbito global (la función referenciada suele tener que existir en window
), dificulta el mantenimiento, y tiende a romper la separación de responsabilidades. Además la sintaxis inline limita la organización y reutilización del código.
Manejo de eventos como funciones (propiedad o API)
Hay dos formas comunes de “manejar como funciones”:
- Asignación a la propiedad del elemento (DOM Level 0):
element.onclick = function (event) { /* ... */ };
- Solo una función por propiedad/evento (una reasignación sobrescribe la anterior).
- Dentro de la función normal,
this
suele referirse al elemento (salvo si se usan arrow functions). - Es simple pero limitado frente a
addEventListener
.
- Usando
addEventListener
(DOM Level 2 / moderno):
element.addEventListener('click', handler /*, options */);
- Permite múltiples listeners para el mismo evento.
- Permite opciones (
capture
,once
,passive
,signal
) y es la práctica recomendada. - Para quitar el listener es necesario la misma referencia a la función y los mismos parámetros de captura.
Manejo de eventos semántico
Por “manejo semántico” se entiende aplicar separación de comportamiento y marcado: no poner código en el HTML, registrar los manejadores desde archivos .js (por ejemplo con addEventListener
o mediante delegación), y dar nombres y estructuras claras a las funciones (p. ej. handleFormSubmit
). Esto facilita accesibilidad, pruebas, mantenibilidad y degradación progresiva.
Variable this
en manejadores
El comportamiento de this
depende de cómo se definió/ligó el manejador:
- En un handler normal asignado con
element.onclick = function (e) { }
o añadido conaddEventListener
(y usando una función normal),this
dentro de la función apunta al elemento que tiene el listener (equivalente aevent.currentTarget
). - En arrow functions (
() => {}
) elthis
es léxico: no se rebindea al elemento, sino que conserva elthis
del ámbito donde se definió la arrow function (por eso no es buena idea usar arrow functions si necesitasthis
como el elemento). call
/apply
/bind
permiten forzar el valor dethis
cuando se invoca una función.- En modo estricto (
'use strict'
) y si una función se invoca “sola” sin contexto,this
puede serundefined
.
Información general sobre el evento (objeto Event
)
Cuando un evento ocurre, el manejador recibe un objeto evento (por ejemplo Event
, MouseEvent
, KeyboardEvent
) con propiedades y métodos útiles:
- Propiedades importantes:
type
(tipo),target
(dónde nació el evento),currentTarget
(elemento que maneja el evento),eventPhase
,bubbles
(si burbujea),cancelable
(si puede cancelarse),isTrusted
,timeStamp
. - Métodos:
preventDefault()
(impide la acción por defecto),stopPropagation()
(evita que el evento suba a ancestros),stopImmediatePropagation()
(además impide otros listeners en el mismo nodo). - Otras utilidades:
event.composedPath()
devuelve la ruta del evento en caso de Shadow DOM;defaultPrevented
indica si ya se llamópreventDefault()
.
Información sobre eventos de teclado (KeyboardEvent
)
KeyboardEvent
añade propiedades específicas:
key
: la representación de la tecla (por ejemplo"a"
,"Enter"
,"ArrowUp"
). Es la recomendada para detectar la tecla lógica.code
: el código físico de la tecla (ej."KeyA"
,"Enter"
), independiente de la distribución de teclado.keyCode
,which
,charCode
: históricos / obsoletos — no son la mejor práctica moderna.- Modificadores:
ctrlKey
,shiftKey
,altKey
,metaKey
. repeat
: indica si la tecla se mantiene pulsada y se están enviando eventos repetidos.getModifierState()
permite consultar estados específicos de modificadores (CapsLock, NumLock, etc.).
Buenas prácticas: usar keydown
/keyup
y key
/code
en vez de keyCode
, y tener en cuenta accesibilidad y comportamiento por defecto (por ejemplo no anular funciones nativas de navegación sin motivo).
Información sobre eventos del mouse (MouseEvent
)
MouseEvent
incluye:
- Coordenadas:
clientX
/clientY
(respecto al viewport),pageX
/pageY
(respecto al documento/page, incluye scroll),screenX
/screenY
(respecto a la pantalla),offsetX
/offsetY
(respecto al elemento),movementX
/movementY
(desplazamiento desde el últimomousemove
). - Botones:
button
(qué botón provocó el evento: 0 primario, 1 medio, 2 secundario) ybuttons
(bitmask con el estado actual de todos los botones). detail
: a menudo indica el número de clicks (contadores en eventosclick
/dblclick
).relatedTarget
: elemento relacionado en eventosmouseover
/mouseout
(ej. el elemento desde el que se provino o al que se dirigió).- Modificadores:
ctrlKey
,shiftKey
,altKey
,metaKey
.
Con todo esto puedes decidir acciones (ej. arrastrar, contexto, coordenadas relativas) y mejorar UX (p. ej. distinguir click derecho, doble click, arrastre).
Formularios
Un formulario (form) es una estructura HTML que agrupa controles (campos de entrada, botones, selects, checkboxes, radios, etc.) para recoger datos del usuario y enviarlos al servidor o procesarlos en el cliente. En JavaScript se puede acceder y manipular el formulario y sus controles para validar, leer, modificar o enviar datos de forma programática.
La etiqueta HTML principal es <form>
. Atributos importantes:
action
: URL donde se envían los datos.method
: método HTTP (GET
oPOST
; por defectoGET
).enctype
: tipo de codificación para envío (por ejemplomultipart/form-data
para archivos).name
yid
: identificadores para referencia en JS/servidor.
Dentro del formulario hay controles<input>
,<textarea>
,<select>
,<button>
, etc. Al enviar (submit) el navegador recoge los valores de los controles conname
y construye el cuerpo de la petición segúnmethod
yenctype
.
Propiedades básicas de los formularios (en JavaScript)
Dado const form = document.forms['miForm']
o document.getElementById('miForm')
:
form.elements
— colección (HTMLFormControlsCollection) de controles del formulario.form.length
— número de controles.form.action
,form.method
,form.enctype
— reflejan atributos.form.submit()
— envía el formulario programáticamente (no disparasubmit
handlers en algunas circunstancias; ver buenas prácticas).form.reset()
— restablece valores al estado inicial del documento HTML.- Cada control tiene propiedades:
value
,checked
,disabled
,name
,id
,type
,form
(referencia al form padre),required
,maxLength
, etc.
Cómo obtener valor de los campos de un formulario
Algunas formas comunes:
- Por id:
document.getElementById('campo').value
. - Por
name
desde el formulario:form.elements['nombreCampo'].value
. - Usando selectores:
document.querySelector('input[name="email"]').value
. - Para radios/checks seleccionados:
document.querySelector('input[name="grupoRadio"]:checked').value
. - Para múltiples checkboxes:
document.querySelectorAll('input[name="interes"]:checked')
y luego recorrer para leer.value
. - Con
FormData
:const fd = new FormData(form); const valor = fd.get('nombreCampo'); // obtiene el primer valor o null
FormData
simplifica recolección y envío (útil confetch
).
Cuadro de texto y <textarea>
<input type="text">
: campo de una sola línea; propiedades:value
,maxLength
,placeholder
.<textarea>
: campo multilínea; atributos:rows
,cols
,maxLength
,placeholder
. En HTML5textarea
soportamaxlength
.
Eventos útiles:input
(en cada cambio mientras tecleas),change
(cuando el control pierde el foco y su valor final cambió).
Radiobuttons (input type=»radio»)
- Forman grupos por su atributo
name
. Solo uno del grupo puede estarchecked
a la vez. - Para obtener el seleccionado:
document.querySelector('input[name="grupo"]:checked')
. - Establecer selección:
document.querySelector('input[name="grupo"][value="x"]').checked = true;
.
Checkbox
input type="checkbox"
representa una opción que puede estar marcada (checked
) o no.- Muchas casillas con el mismo
name
pueden usarse para seleccionar múltiples valores; usaquerySelectorAll('input[name="x"]:checked')
para obtener las seleccionadas. - Propiedad
checked
(boolean) indica estado;indeterminate
(solo UI) indica estado visual intermedio (no enviado por formulario).
Select
<select>
para listas desplegables;<option>
elementos dentro.multiple
permite seleccionar más de una opción.- Propiedades importantes del elemento select:
select.value
— valor de la opción seleccionada (enmultiple
devuelve el primer seleccionado).select.selectedIndex
— índice de la opción seleccionada (-1 si no hay).select.selectedOptions
— colección de las opciones seleccionadas (HTMLCollection).select.options
— colección de todas lasoption
.select.length
— número de opciones.
Propiedades del select (resumen)
multiple
(boolean) — habilita selección múltiple.options
— colección de<option>
(acceso por índice, p. ej.options[0]
).selectedIndex
— índice seleccionado; asignable para cambiar selección.selectedOptions
— colección con las opciones seleccionadas.value
— valor de la opción seleccionada (por defecto suvalue
o su texto si no tienevalue
).
Cómo establecer foco a un elemento
element.focus()
— pone el foco en el control (si es focusable).element.blur()
— quita el foco del control.- Atributos HTML:
autofocus
en el control para que el navegador intente darle foco al cargar. tabindex
controla el orden de tabulación y permite elementos no focusables por defecto recibir foco.
Cómo limitar tamaño de caracteres en elementos de formularios
Atributo HTML maxlength="n"
en <input>
y <textarea>
limita la cantidad de caracteres que el usuario puede introducir.
En JavaScript se puede forzar o complementar con un listener input
:
input.addEventListener('input', e => {
const max = input.maxLength; // o un número fijo
if (input.value.length > max) input.value = input.value.slice(0, max);
});
También se pueden usar pattern
(expresiones regulares) y validación con checkValidity()
/reportValidity()
para requisitos más complejos.
Restringir caracteres en un elemento
Restringir caracteres consiste en limitar la entrada de datos que un usuario puede escribir en un campo de formulario (por ejemplo, un input
). Esto se hace mediante validaciones con JavaScript, donde se puede permitir solo letras, solo números o caracteres específicos. Una técnica común es usar eventos como keypress
, keydown
o input
para filtrar la entrada en tiempo real, evitando que se introduzcan caracteres no deseados.
Validación de un formulario
La validación de un formulario es el proceso de verificar que los datos introducidos por el usuario cumplen con ciertos requisitos antes de ser enviados al servidor. Esto mejora la calidad de la información, evita errores y protege contra datos inválidos o maliciosos. Se puede realizar con validaciones en el lado del cliente (JavaScript) y/o en el lado del servidor.
Campo Obligatorio
Un campo obligatorio es aquel que no puede quedar vacío al enviar el formulario. En HTML puede declararse con el atributo required
, y con JavaScript se valida verificando si el campo contiene algún valor. Su función es asegurar que el usuario ingrese información indispensable.
Campo con solo Números
Un campo que debe aceptar únicamente números se valida usando expresiones regulares o funciones de verificación en JavaScript. Generalmente se captura la entrada y se comprueba que cada carácter sea un dígito (0–9
). También puede usarse el atributo type="number"
en HTML5, aunque a menudo se complementa con validación en JavaScript.
Validar selección de un elemento de una lista
En un select
, se valida que el usuario haya elegido una opción válida y no se quede con la opción por defecto (generalmente algo como “Seleccione una opción…”). Con JavaScript se comprueba el valor del select
para asegurar que no esté vacío ni sea inválido.
Validar Email
La validación de correos electrónicos consiste en verificar que la entrada del usuario tenga el formato correcto: un nombre de usuario, seguido de @
, un dominio y una extensión válida. Se suelen usar expresiones regulares como:
/^[^\s@]+@[^\s@]+\.[^\s@]+$/
Esto garantiza que el correo tenga la estructura básica, aunque no asegura que el correo exista realmente.
Validar Fecha
La validación de fecha busca comprobar que el usuario haya introducido una fecha en formato válido (por ejemplo dd/mm/yyyy
o yyyy-mm-dd
). JavaScript permite trabajar con objetos Date
para verificar que la fecha sea real (ejemplo: no permitir 31 de febrero) y que cumpla restricciones como rango de años o fechas futuras/pasadas.
Validar DNI
El Documento Nacional de Identidad (DNI) u otros identificadores personales requieren validaciones específicas. Generalmente se comprueba la longitud (por ejemplo, 8 dígitos), que solo tenga números, y en algunos países se incluye una letra de control al final que se valida con algoritmos. La validación con JavaScript garantiza que el formato sea correcto antes de enviarlo al servidor.
Validar Teléfono
La validación de un número de teléfono asegura que la entrada del usuario tenga un formato válido, generalmente consistente en un código de área seguido de una secuencia de dígitos. Puede incluir o no símbolos como +
, -
, paréntesis o espacios. En JavaScript, se utilizan expresiones regulares para verificar la estructura del número y prevenir errores antes de enviarlo al servidor. Ejemplo de patrón simple:
/^\+?\d{1,3}?[-.\s]?\(?\d{1,4}?\)?[-.\s]?\d{5,10}$/
Objeto Math
El objeto Math
de JavaScript es un objeto estático que proporciona propiedades y métodos para realizar operaciones matemáticas. Algunos ejemplos:
Math.PI
— valor de π.Math.round(x)
— redondea al entero más cercano.Math.floor(x)
— redondea hacia abajo.Math.ceil(x)
— redondea hacia arriba.Math.random()
— devuelve un número aleatorio entre 0 y 1.Math.max(a,b,...)
yMath.min(a,b,...)
— máximos y mínimos de varios números.
Objeto Date
El objeto Date
permite trabajar con fechas y horas en JavaScript. Con él se puede obtener la fecha actual, manipular días, meses, años, horas, minutos y segundos. Ejemplos de uso:
const hoy = new Date(); // fecha y hora actual
const año = hoy.getFullYear(); // obtiene el año
const mes = hoy.getMonth(); // obtiene el mes (0-11)
Se puede crear una fecha específica y calcular diferencias entre fechas.
setInterval()
setInterval()
es una función que ejecuta repetidamente otra función cada intervalo de tiempo especificado en milisegundos. Su sintaxis:
let id = setInterval(funcion, intervalo);
Se puede detener con clearInterval(id)
.
setTimeout()
setTimeout()
ejecuta una función una sola vez después de un tiempo determinado en milisegundos. Ejemplo:
setTimeout(() => { console.log("Hola"); }, 2000);
Esto muestra «Hola» después de 2 segundos.
Corrección de Errores
La corrección de errores en JavaScript consiste en identificar y solucionar problemas en el código que provocan comportamientos inesperados. Puede involucrar:
- Errores de sintaxis: faltan paréntesis, llaves, comillas, etc.
- Errores de ejecución: ocurren al ejecutar código válido sintácticamente (ej.: dividir por 0, acceder a variables no definidas).
- Errores lógicos: el código funciona pero produce resultados incorrectos.
Herramientas:
- Consola del navegador (
console.log
,console.error
). - Depuradores (debugger).