Errores, depuración y almacenamiento
💡 🎯 Al terminar esta lección podrás…
- Capturar y lanzar errores con
try/catch/finallyythrow. - Depurar con un método y con las herramientas del navegador.
- Guardar y leer datos con
localStoragey JSON de forma segura. - Organizar el código con módulos y aplicar hábitos de código limpio.
1.Los errores: tipos y causas
Todo programa tiene errores, y aprender a leerlos, controlarlos y encontrarlos es lo que separa a quien empieza de quien programa con soltura. JavaScript distingue varios tipos:
| Error | Cuándo ocurre | Ejemplo |
|---|---|---|
SyntaxError | El código está mal escrito y ni siquiera arranca | Una llave o comilla sin cerrar |
ReferenceError | Usas un nombre que no existe | console.log(variableInexistente) |
TypeError | Haces algo con un valor del tipo equivocado | null.nombre, 5() |
RangeError | Un valor fuera de rango | new Array(-1), recursión infinita |
Error (propio) | Los que tú lanzas con throw | throw new Error("Falta el nombre") |
2.try, catch, finally y throw
try {
// código que PUEDE fallar
const datos = JSON.parse(texto);
mostrar(datos);
} catch (error) {
// qué hacer si falla
console.error("No se pudo leer:", error.message);
} finally {
// se ejecuta SIEMPRE, haya o no error (limpieza)
ocultarCargando();
}
| Parte | Para qué |
|---|---|
try { … } | Código que puede fallar |
catch (error) { … } | Se ejecuta solo si hubo error; error.message explica qué pasó |
finally { … } | Se ejecuta siempre: ideal para quitar un «cargando…» |
throw new Error("…") | Lanzas tú un error cuando algo no es válido |
💡 Consejo · Falla pronto y con claridad
Valida los datos al principio de una función y lanza un error con un mensaje útil: «Falta el precio» es mucho mejor que dejar que el programa falle tres funciones después con un críptico NaN. Y captura los errores solo donde puedas hacer algo útil con ellos.
3.Depurar: encontrar el error
Depurar (*debugging*) es el arte de encontrar por qué algo no hace lo que esperas. El método siempre es el mismo:
- Reproduce el problema de forma fiable.
- Lee el mensaje de error y la línea que indica.
- Formula una hipótesis: ¿qué valor creo que tiene cada variable aquí?
- Compruébala con
console.logo con el depurador. - Corrige una cosa y vuelve a probar.
Más allá de console.log
El depurador del navegador
Con F12 → pestaña Fuentes (*Sources*) puedes detener el programa en una línea y mirarlo desde dentro:
| Herramienta | Qué hace |
|---|---|
| Punto de interrupción (*breakpoint*) | Clic en el número de una línea: el programa se pausa ahí |
debugger; | Una instrucción que pausa el programa si las herramientas están abiertas |
| Paso a paso (*step over / into*) | Avanza una línea (o entra en la función que se llama) |
| Variables locales y *Watch* | Ver (y vigilar) el valor de cada variable en ese momento |
| Pila de llamadas (*call stack*) | Qué funciones llevaron hasta aquí |
| Pestaña Red (*Network*) | Ver cada petición, su respuesta y su tiempo |
📌 Nota · Leer una pila de errores
Cuando un error aparece en la consola, la pila (*stack trace*) lista las funciones por las que pasó, de la más reciente (arriba) a la más antigua. Busca la primera línea que sea de tu código: casi siempre ahí está el problema.
4.Guardar datos en el navegador: localStorage
Las variables desaparecen al recargar la página. Para conservar datos (una lista de tareas, una preferencia, un carrito) el navegador ofrece localStorage: un pequeño almacén de pares clave–valor que persiste aunque cierres el navegador.
| Método | Qué hace |
|---|---|
localStorage.setItem(clave, valor) | Guarda un valor (siempre como texto) |
localStorage.getItem(clave) | Lo lee; devuelve null si no existe |
localStorage.removeItem(clave) | Borra una clave |
localStorage.clear() | Borra todo lo guardado por tu sitio |
📌 Nota · En este editor es temporal
Por seguridad, los editores del curso funcionan en un entorno aislado y simulan localStorage en memoria: los datos no sobreviven a recargar. En tu propia página, sí quedarán guardados de verdad. Compruébalo en F12 → Aplicación (*Application*) → Almacenamiento local.
| Aspecto | localStorage | sessionStorage | Cookies |
|---|---|---|---|
| Dura | Hasta que se borre | Hasta cerrar la pestaña | Según su caducidad |
| Tamaño | ~5 MB | ~5 MB | ~4 KB |
| Se envía al servidor | No | No | Sí, en cada petición |
| Típico | Preferencias, borradores, listas | Datos de una sesión | Inicio de sesión (lo gestiona el servidor) |
5.Guardar con seguridad
- Convierte con JSON al guardar y al leer.
- Lee siempre con un valor por defecto:
?? [], porque la primera vez no hay nada. - Envuelve
JSON.parseentry/catch: alguien puede haber alterado el dato. - Usa un nombre de clave con prefijo (
miapp:tareas) para no chocar con otros datos.
const CLAVE = "miapp:tareas";
function leerTareas() {
try {
return JSON.parse(localStorage.getItem(CLAVE)) ?? [];
} catch {
return []; // dato corrupto: empezamos de cero
}
}
function guardarTareas(tareas) {
localStorage.setItem(CLAVE, JSON.stringify(tareas));
}
⚠️ Importante · Nunca guardes secretos
localStorage no es seguro: cualquier script de la página (y cualquiera que use ese navegador) puede leerlo. No guardes contraseñas, tokens de acceso ni datos personales sensibles. Úsalo para preferencias y datos sin riesgo.
6.Organizar el código: módulos
Cuando un programa crece, un solo archivo de 800 líneas se vuelve inmanejable. Los módulos de ES dejan dividir el código en archivos con una responsabilidad cada uno, que exportan lo que ofrecen e importan lo que necesitan:
const CLAVE = "miapp:tareas";
export function leerTareas() { /* … */ }
export function guardarTareas(tareas) { /* … */ }
export const MAXIMO = 100;
export default function crearTarea(texto) {
return { id: Date.now(), texto, hecha: false };
}
import crearTarea, { leerTareas, guardarTareas, MAXIMO } from "./tareas.js";
const tareas = leerTareas();
tareas.push(crearTarea("Estudiar módulos"));
guardarTareas(tareas);
<script type="module" src="js/app.js"></script>
type="module"activa los módulos; ya se comporta comodefer.- Las variables de un módulo son privadas a él salvo que las exportes.
- Las rutas de
importempiezan con./o../y llevan la extensión.js. - Los módulos no funcionan abriendo el archivo directamente (
file://): necesitas un servidor, por ejemplo la extensión Live Server del editor (funciona también en Cursor).
💡 Consejo · Cómo dividir
Una guía sencilla: un archivo para los datos y su almacenamiento, otro para la lógica (funciones puras) y otro para la interfaz (DOM y eventos). Si dudas, pregúntate: «¿puedo probar esta función sin una página?»
7.Hábitos de código limpio
- Nombres claros que digan qué hace o qué contiene cada cosa.
- Funciones pequeñas con una sola tarea.
- Evita los «números mágicos»:
const MAXIMO_TAREAS = 100;en lugar de un100suelto. - Una sola fuente de verdad: no repitas el mismo dato en dos sitios.
- Comenta el porqué, no lo evidente.
- Valida las entradas y trata los errores.
- Formatea con una herramienta (Prettier) y revisa con un linter (ESLint): encuentran errores antes de ejecutar.
- Activa el modo estricto (
"use strict";, o usa módulos, que ya lo tienen): convierte fallos silenciosos en errores.
📌 Nota · Seguridad básica
Nunca confíes en los datos que llegan de fuera (formularios, URL, APIs): valídalos y, al mostrarlos, usa textContent. Cualquier verificación importante (precios, permisos) debe repetirse en el servidor, porque el código del navegador se puede modificar.
8.Errores frecuentes
- Guardar objetos sin
JSON.stringify: acaban como"[object Object]". - Olvidar el valor por defecto al leer:
JSON.parse(null)danully rompe lo que sigue. - No usar
try/catchconJSON.parsede datos externos. - Atrapar un error y no hacer nada (
catch {}): oculta los problemas. Al menos regístralo. - Guardar secretos en
localStorage. - Depurar a ciegas: cambiar cosas al azar en vez de comprobar el valor de las variables.
- Abrir módulos con doble clic (
file://) y sorprenderse por los errores de CORS. - Modificar el estado y olvidar volver a guardarlo.
📒 Apuntes para llevar
- Los errores se clasifican (
SyntaxError,ReferenceError,TypeError…); la consola indica el tipo, el mensaje y la línea. try { … } catch (error) { … } finally { … }controla los fallos;throw new Error("…")lanza los propios.- Valida al principio y falla con mensajes claros; captura solo donde puedas hacer algo útil.
- Depura con método: reproduce, lee, formula una hipótesis, comprueba y corrige una cosa a la vez.
console.table,group,assert, los puntos de interrupción ydebuggervan mucho más allá deconsole.log.localStorageguarda texto de forma persistente: usaJSON.stringify/parsey un valor por defecto al leer.- No guardes secretos en el navegador;
sessionStoragedura una pestaña y las cookies se envían al servidor. - Los módulos (
import/export,type="module") dividen el código; Prettier, ESLint y los nombres claros lo mantienen sano.
9.Glosario
| Término | Significado |
|---|---|
| Excepción | Error que se «lanza» y detiene el programa si nadie lo atrapa. |
try / catch | Estructura que controla errores. |
throw | Lanza un error a propósito. |
| Depurar | Encontrar y corregir la causa de un error. |
| Punto de interrupción | Marca donde el depurador pausa el programa. |
localStorage | Almacén persistente de pares clave–valor en el navegador. |
| Módulo | Archivo que exporta e importa partes de código. |
| Linter | Herramienta que revisa el código y avisa de problemas. |
🧠 Comprueba lo aprendido
Elige una respuesta en cada pregunta. Verás al instante si acertaste y por qué.
¿Cuándo se ejecuta el bloque finally?
Se ejecuta siempre, haya o no error: ideal para limpiar.
localStorage.setItem("lista", [1, 2, 3]) guarda…
Convierte el valor a texto: para arrays y objetos usa JSON.stringify.
¿Qué devuelve localStorage.getItem("clave") si la clave no existe?
Devuelve null. Por eso se usa ?? valorPorDefecto.
¿Cuál de estas cosas no deberías guardar en localStorage?
Cualquier script de la página puede leer localStorage: no es lugar para secretos.
En un error, ¿dónde suele estar el problema dentro de la pila (stack trace)?
Busca la primera referencia a tus archivos.
Tu progreso se guarda en este navegador y se refleja en el índice del curso.
💡 🚀 ¡Ahora te toca!
La práctica fija lo aprendido. Pasa al ejercicio de esta lección.