Definición y Funcionalidad de JavaScript

Definición y Funcionalidad de JavaScript

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 permite import/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 con undefined).
  • 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 una const 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): devuelve true si ambas expresiones son verdaderas.
  • || (OR): devuelve true 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 devuelve a si es falsy, de lo contrario devuelve b; a || b devuelve a si es truthy, de lo contrario devuelve b.

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 y const 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 de var 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 usa return, la función devuelve undefined. 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 es obj)
  • Con call/apply para fijar this y pasar argumentos (fn.call(thisArg, a, b) / fn.apply(thisArg, [a,b]))
  • Con bind para crear una nueva función con this 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 con getAttribute/setAttribute o como propiedades del elemento.
    (Nota: cada tipo tiene una constante en la API Node, 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 devuelve oldNode.
  • element.append(nodeOrString) — moderno: admite nodos y cadenas.
    Eliminar:
  • parent.removeChild(child) — elimina y devuelve child.
  • 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 la value de un <input> refleja el valor actual del control, mientras que getAttribute('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 atributos data-* mediante propiedades camelCase (p. ej. data-user-idelement.dataset.userId).
  • Para clases existe element.className (cadena) y element.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:

  1. Captura (capturing phase): el evento baja desde el document hacia el nodo objetivo pasando por los ancestros.
  2. Fase objetivo (target phase): el evento llega al nodo objetivo.
  3. 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 mediante AbortController.

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 sobre on* para permitir múltiples listeners y mayor control.
  • Usar passive: true para listeners de scroll y touchstart cuando no se usa preventDefault() para mejorar rendimiento.
  • Delegar eventos cuando se manejan muchos elementos dinámicos.
  • Evitar listeners pesados en el hilo principal (usar requestAnimationFrame para animaciones o Web 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 usar once: 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”:

  1. 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.
  1. 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 con addEventListener (y usando una función normal), this dentro de la función apunta al elemento que tiene el listener (equivalente a event.currentTarget).
  • En arrow functions (() => {}) el this es léxico: no se rebindea al elemento, sino que conserva el this del ámbito donde se definió la arrow function (por eso no es buena idea usar arrow functions si necesitas this como el elemento).
  • call/apply/bind permiten forzar el valor de this cuando se invoca una función.
  • En modo estricto ('use strict') y si una función se invoca “sola” sin contexto, this puede ser undefined.

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 último mousemove).
  • Botones: button (qué botón provocó el evento: 0 primario, 1 medio, 2 secundario) y buttons (bitmask con el estado actual de todos los botones).
  • detail: a menudo indica el número de clicks (contadores en eventos click/dblclick).
  • relatedTarget: elemento relacionado en eventos mouseover/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 o POST; por defecto GET).
  • enctype: tipo de codificación para envío (por ejemplo multipart/form-data para archivos).
  • name y id: 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 con name y construye el cuerpo de la petición según method y enctype.

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 dispara submit 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 con fetch).

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 HTML5 textarea soporta maxlength.
    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 estar checked 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; usa querySelectorAll('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 (en multiple 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 las option.
    • 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 su value o su texto si no tiene value).

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,...) y Math.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).