Lección 38: Optional Chaining (?.)
🧠 Concepto
Section titled “🧠 Concepto”El optional chaining (?.) permite acceder a propiedades anidadas de un objeto sin tener que verificar explícitamente si cada nivel existe. Si algún nivel es null o undefined, la expresión retorna undefined en lugar de lanzar un error.
Sintaxis básica
Section titled “Sintaxis básica”const usuario = { nombre: 'Ana', direccion: { ciudad: 'Madrid' }};
// Sin optional chainingconst ciudad = usuario && usuario.direccion && usuario.direccion.ciudad;console.log(ciudad); // "Madrid"
// Con optional chainingconst ciudad2 = usuario?.direccion?.ciudad;console.log(ciudad2); // "Madrid"
// Si algo es null/undefined no da errorconst usuarioVacio = null;console.log(usuarioVacio?.nombre); // undefined (no error)Variantes
Section titled “Variantes”// Acceso a propiedades dinámicasconst key = 'nombre';console.log(usuario?.[key]); // "Ana"
// Acceso a índices de arrayconst arr = [1, 2, 3];console.log(arr?.[0]); // 1console.log(arr?.[10]); // undefined (sin error)const arrNull = null;console.log(arrNull?.[0]); // undefined
// Llamar a funciones que pueden no existirconst obj = { saludar() { return 'Hola'; }};console.log(obj.saludar?.()); // "Hola"console.log(obj.despedir?.()); // undefined (sin error)💻 Ejemplo
Section titled “💻 Ejemplo”// Caso real: respuesta de APIconst respuestaAPI = { data: { usuario: { perfil: { nombre: 'Carlos', preferencias: { tema: 'oscuro' } } } }};
// Acceso seguro a niveles profundosconst tema = respuestaAPI?.data?.usuario?.perfil?.preferencias?.tema;console.log(tema); // "oscuro"
// Si falta algún nivel, undefined sin errorconst tema2 = respuestaAPI?.data?.otro?.preferencias?.tema;console.log(tema2); // undefined
// Combinación con nullish coalescingconst temaFinal = respuestaAPI?.data?.usuario?.perfil?.preferencias?.tema ?? 'claro';console.log(temaFinal); // "oscuro"⚠️ Nota
Section titled “⚠️ Nota”El optional chaining no se puede usar en el lado izquierdo de una asignación:
// Esto NO funciona:// usuario?.nombre = 'Luis'; // SyntaxError// Debes verificar manualmente:if (usuario) { usuario.nombre = 'Luis';}Tampoco funciona con delete:
// Esto NO funciona:// delete usuario?.nombre; // SyntaxErrorEl operador cortocircuita: si encuentra null/undefined, no evalúa el resto de la expresión. Esto es importante si hay efectos secundarios.
Usa optional chaining en lugar de largas cadenas de && para acceder a propiedades profundas. Es especialmente útil con:
- Respuestas de APIs (donde la estructura puede variar)
- Configuraciones opcionales
- Props de componentes que pueden ser undefined
- Navegación por DOM (donde elementos pueden no existir)
No abuses de ?. en propiedades que sabes que siempre existen, ya que puede ocultar bugs.
📝 Ejercicio
Section titled “📝 Ejercicio”Refactoriza el siguiente código usando optional chaining:
// Código originalfunction getPreferenciaTema(usuario) { if (usuario && usuario.config && usuario.config.preferencias) { return usuario.config.preferencias.tema; } return 'claro';}
// Escríbelo con optional chaining y nullish coalescingfunction getPreferenciaTemaRefactor(usuario) { // Tu código aquí}