Errores y excepciones en JavaScript
En esta lección
Cuando algo sale mal durante la ejecución (acceder a una propiedad de undefined, llamar a algo que no es una función, recibir un JSON mal escrito…), JavaScript lanza una excepción: detiene lo que estaba haciendo y, si nadie la captura, el programa se para y aparece el error en rojo en la consola.
Leer un error
Uncaught TypeError: Cannot read properties of undefined (reading 'nombre')
at mostrarUsuario (app.js:12:24)
at app.js:20:1
- Tipo:
TypeError. - Mensaje: qué ha pasado. Aquí, que intentaste leer
nombrede algo que valeundefined. - Traza (stack trace): dónde ha pasado. Archivo
app.js, línea 12, columna 24, dentro de la funciónmostrarUsuario, que fue llamada desde la línea 20.
Aprender a leer los errores es la mitad de programar. Lee siempre el mensaje completo y ve a la línea que indica.
Capturar errores: try y catch
try {
// código que puede fallar
const datos = JSON.parse(textoRecibido);
mostrar(datos);
} catch (error) {
// qué hacer si falla
console.log("Los datos recibidos no son válidos:", error.message);
}
- Se ejecuta el bloque
try. - Si todo va bien, el
catchse salta. - Si algo lanza una excepción, el
tryse interrumpe en ese punto y se ejecuta elcatch. El programa sigue después.
finally
El bloque finally se ejecuta siempre, haya error o no. Se usa para “recoger”: cerrar un indicador de carga, liberar un recurso…
mostrarCargando();
try {
await cargarDatos();
} catch (error) {
mostrarError("No se pudieron cargar los datos");
} finally {
ocultarCargando(); // pase lo que pase
}
El objeto error
Los errores que lanza JavaScript son objetos con, al menos, dos propiedades:
error.name: el tipo de error.error.message: la descripción.
Los tipos que más verás:
| Tipo | Cuándo aparece |
|---|---|
ReferenceError | Usas una variable que no existe (a menudo, una errata) |
TypeError | Usas un valor de forma incorrecta: leer una propiedad de undefined, llamar a algo que no es una función, reasignar una const |
SyntaxError | El código (o un JSON) está mal escrito |
RangeError | Un número fuera del rango permitido |
URIError | Error al codificar o decodificar una URL |
Error | Error genérico |
Puedes reaccionar de forma distinta según el tipo:
try {
procesar();
} catch (error) {
if (error instanceof TypeError) {
console.log("Dato con formato incorrecto");
} else {
throw error; // no sé qué es: lo vuelvo a lanzar
}
}
Lanzar tus propios errores: throw
Cuando tu función recibe algo con lo que no puede trabajar, lo correcto es lanzar un error en vez de devolver un valor raro o seguir como si nada:
function calcularEdad(anioNacimiento) {
if (!Number.isInteger(anioNacimiento)) {
throw new TypeError("El año de nacimiento debe ser un número entero");
}
const actual = new Date().getFullYear();
if (anioNacimiento > actual) {
throw new RangeError("El año de nacimiento no puede ser futuro");
}
return actual - anioNacimiento;
}
Técnicamente puedes lanzar cualquier cosa (throw "error", throw 42), pero lanza siempre objetos de error (new Error(...), new TypeError(...)): incluyen la traza y se comportan como los errores del propio lenguaje.
Cuándo capturar (y cuándo no)
Los ejemplos de los tutoriales suelen lanzar un error y capturarlo en la misma función. Sirve para aprender la sintaxis, pero en un programa real no tiene sentido: si lo vas a capturar ahí mismo, usa un if.
Lo normal es:
- La función que detecta el problema lo lanza (
throw). No sabe qué hacer con él; solo sabe que no puede continuar. - Quien llama a la función, que sí sabe qué hacer, lo captura: mostrar un mensaje al usuario, reintentar, usar un valor por defecto.
- Si nadie sabe qué hacer, no lo captures: deja que el programa se detenga y el error aparezca en la consola. Es mejor que seguir funcionando con datos incorrectos.
Y un error clásico: capturar y no hacer nada.
try {
guardar();
} catch (error) {
// silencio...
}
Así el problema desaparece de la vista, pero sigue ahí. Como mínimo, registra el error con console.error(error).
Errores que JavaScript no avisa
Algunos fallos no lanzan excepción, y por eso son más peligrosos:
- Leer una propiedad que no existe:
usuario.nombrdevuelveundefinedsin avisar. - Operaciones matemáticas imposibles:
"hola" * 2daNaN. - Llamar a una función con menos argumentos: los que faltan valen
undefined.
Para detectarlos, pon trazas con console.log mientras desarrollas (sobre todo al empezar, aunque todo parezca ir bien) o usa TypeScript, que detecta muchos de ellos antes de ejecutar el código.
Pruébalo tú
Cambia el código y pulsa Ejecutar (o Ctrl + Enter).
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.