Saltar al contenido principal
05Objetos

Operador de encadenamiento opcional

Clase 4 de 47 min de lectura

Intenta leer una propiedad de algo que no existe y… se rompe tu aplicación. Es uno de los tropiezos más habituales en JavaScript, y tiene arreglo.

Hay varias formas de evitarlo. Las repasamos de la más aparatosa a la más elegante, hasta llegar al operador de encadenamiento opcional, también llamado Optional Chaining.

Te va a salvar sobre todo cuando trabajes con objetos de estructura compleja, o con datos que pueden no estar definidos en algún momento de la ejecución.

El error fatal de intentar leer una propiedad de undefined#

Uno de los errores más comunes en JavaScript, y te aseguro que lo verás tarde o temprano, es el que dice que no puedes leer una propiedad de undefined.

Aparece cuando intentas acceder a una propiedad de algo que no existe. Mira la última línea:

const gamesystem = {  name: 'PS5',  price: 550,  specs: {    cpu: 'AMD Ryzen Zen 2',    gpu: 'AMD Radeon RDNA 2',  }}console.log(gamesystem.name) // -> PS5console.log(gamesystem.specifications) // -> undefinedconsole.log(gamesystem.specifications.ram) // ❌ Uncaught TypeError: Cannot read properties of undefined (reading 'ram')

Parece un despiste inocente: hemos escrito specifications en lugar de specs. Leer una propiedad que no existe no es grave, devuelve undefined. El problema llega justo después, cuando le pedimos ram a ese undefined. Ahí JavaScript dice basta.

Evitando el error con if

La primera solución que se te ocurriría: comprobar con un if que la propiedad existe antes de seguir.

if (typeof gamesystem.specifications === 'object') {  console.log(gamesystem.specifications.ram)} else {  console.log('No hay especificaciones')}

Usamos el operador typeof, que ya vimos en la primera sección del curso, para asegurarnos de que specifications existe y es un objeto antes de leer su propiedad ram.

El operador in para comprobar si una propiedad existe#

Otra opción es el operador in. Le preguntas si una propiedad existe en un objeto y te contesta true o false:

console.log('name' in gamesystem) // -> trueconsole.log('specifications' in gamesystem) // -> falseconsole.log('specs' in gamesystem) // -> trueif ('specifications' in gamesystem) {  console.log(gamesystem.specifications.ram)} else {  console.log('No hay especificaciones')}

Tiene buena pinta. Pero ¿qué pasa si la propiedad existe y su valor es undefined?

const gamesystem = {  name: 'PS5',  price: 550,  specifications: undefined,}console.log('specifications' in gamesystem) // -> truegamesystem.specifications.ram // ❌ Uncaught TypeError: Cannot read properties of undefined (reading 'ram')

Que volvemos a la casilla de salida. El operador in te dice si la propiedad existe, pero no si su valor es undefined o null. Para ir sobre seguro tendrías que añadir más comprobaciones:

if (  'specifications' in gamesystem &&  gamesystem.specifications !== undefined &&  gamesystem.specifications !== null) {  console.log(gamesystem.specifications.ram)} else {  console.log('No hay especificaciones')}

Mucho código para algo tan simple. Por suerte, hay una forma más corta.

El operador de Encadenamiento Opcional, ?.#

El operador de encadenamiento opcional ?. te deja leer una propiedad que está en lo más profundo de una cadena de objetos sin validar a mano cada eslabón. Es como el punto de siempre, pero prudente: antes de seguir, mira si hay algo a su izquierda.

const gamesystem = {  name: 'PS5',  price: 550,  specs: {    cpu: 'AMD Ryzen Zen 2',    gpu: 'AMD Radeon RDNA 2',  }}console.log(gamesystem.specifications?.cpu)// -> undefinedconsole.log(gamesystem.specs?.cpu)// -> AMD Ryzen Zen 2

Como specifications no existe, ?. se detiene, devuelve undefined y no hay ningún error. Como specs sí existe, ?. se comporta como un punto normal y devuelve el valor de cpu.

Infografía
Qué hace el operador ?.
5.Si la propiedad sí existe, ?. se comporta como el punto: gamesystem.specs?.cpu devuelve el valor.
Paso 5 de 5

Beneficios del Operador de Encadenamiento Opcional

El gran beneficio es que el código queda más corto y más legible. En vez de encadenar comprobaciones para asegurarte de que existen el objeto y cada una de sus propiedades, vas directo a la que te interesa. Si algo falta por el camino, JavaScript no se queja.

Lo vas a agradecer especialmente con datos dinámicos, donde no siempre puedes garantizar la estructura exacta de los objetos. Compara las dos formas de leer el mismo dato:

const user = {  name: 'Peter',  settings: {    theme: 'dark',    notifications: {      email: true,      push: false,      marketing: undefined    }  }}// la forma clásica de acceder a una propiedad anidada// de forma seguralet email = undefinedif (user && user.settings &&  user.settings.notifications &&  user.settings.notifications.email) {  email = user.settings.notifications.email}console.log(email) // -> true// con Optional Chaining Operatorconst safeEmail = user?.settings?.notifications?.emailconsole.log(safeEmail) // -> true

Seis líneas contra una, y el mismo resultado. Cuando no puedes garantizar la estructura o la presencia de ciertos datos, el encadenamiento opcional te ayuda a escribir un código más limpio, legible y resistente a errores.

En resumen

  • Leer una propiedad de undefined o null lanza un TypeError y detiene tu código.
  • Comprobarlo con if, typeof o el operador in funciona, pero obliga a encadenar muchas comprobaciones.
  • objeto.propiedad?.otra devuelve undefined si lo que hay antes de ?. es undefined o null, sin lanzar error.
  • Puedes encadenar varios ?. para leer datos muy anidados de forma segura.