Menu

Optional Chaining en JavaScript (?.): acceso seguro

Cómo el operador ?. te permite acceder a propiedades anidadas, arrays y métodos sin que todo explote cuando algo es null o undefined.

El problema: acceder a propiedades anidadas es frágil

Entrar a un objeto anidado funciona de maravilla… hasta que uno de los niveles no existe:

index.js
Output
Click Run to see the output here.

user.address es undefined, y leer .city sobre undefined lanza TypeError: Cannot read properties of undefined. En el mundo real, los datos están llenos de campos que pueden o no existir (respuestas de una API, JSON parseado, consultas al DOM...), y escribir comprobaciones defensivas nivel por nivel se vuelve ruidoso enseguida:

const city = user && user.address && user.address.city;

Legible con dos niveles. Insufrible con cuatro. El operador ?. es la solución limpia.

El operador ?. hace corto-circuito con null y undefined

El optional chaining en JavaScript lee una propiedad solo si el valor anterior no es null ni undefined. Si lo es, toda la expresión devuelve undefined y ahí se corta.

index.js
Output
Click Run to see the output here.

La primera línea lee name sin problema. La segunda intenta acceder a user.address, se encuentra con undefined y corta por lo sano: el resto de la cadena ni siquiera se ejecuta. La tercera tiraría un error sin ?., porque estaríamos llamando a .toUpperCase() sobre undefined; con ?., toda la expresión simplemente devuelve undefined sin hacer ruido.

La idea que conviene grabarse: ?. significa "si lo que tengo antes es null o undefined, me rindo y devuelvo undefined; si no, sigo adelante".

También funciona con arrays y llamadas a funciones

Tres formas distintas, la misma idea de fondo:

index.js
Output
Click Run to see the output here.
  • ?.[...] para acceder a arrays o propiedades dinámicas.
  • ?.() para invocar algo que puede o no ser una función.
  • ?.name para acceso normal a propiedades.

Las tres variantes cortocircuitan igual. Por ejemplo, user?.notAMethod?.() no lanza error aunque notAMethod no exista: el segundo ?. detecta undefined y se detiene ahí.

Esto viene de maravilla con callbacks opcionales:

index.js
Output
Click Run to see the output here.

Se acabó lo de poner if (typeof onDone === "function") antes de cada invocación.

Solo null y undefined activan el cortocircuito

Este es el detalle que suele pillar a mucha gente por sorpresa. Al operador ?. solo le importan los valores nullish. El resto de valores falsy0, "", false, NaN — son objetos perfectamente válidos sobre los que encadenar (bueno, hasta donde el autoboxing lo permite):

index.js
Output
Click Run to see the output here.

data.count vale 0: es un valor falsy, pero no es nullish, así que ?.toFixed(2) sí se ejecuta sobre él y devuelve "0.00". Compáralo con lo que pasa usando &&:

index.js
Output
Click Run to see the output here.

La versión con && devuelve 0 porque data.count es falsy y corta la evaluación. La del ?., en cambio, devuelve "0.00" porque 0 no es nullish. Si de verdad quieres detenerte en 0, usa &&. Si solo quieres frenar cuando "el valor no existe", lo tuyo es ?..

La posición del ? importa

El operador ?. protege el valor que tiene antes, no el que viene después. Por eso debes colocarlo en el nivel que podría faltar:

index.js
Output
Click Run to see the output here.

Los tres funcionan aquí porque en realidad no falta nada. Pero si config.server pudiera ser undefined, necesitas config.server?.host: poner un ?. antes de server no ayudaría, porque el problema está en leer .host sobre un server que no existe.

Una buena regla: pon ?. en cada nivel donde el valor que tiene antes pueda ser realmente null o undefined. Meter ?. en cada punto "por si acaso" oculta bugs y ensucia el código.

Asignar a través de ?. no funciona

El optional chaining es solo de lectura. No puedes usarlo en la parte que recibe una asignación:

user?.address?.city = "Paris";   // SyntaxError

Tiene sentido si lo piensas un momento: ¿qué significaría asignar un valor a una propiedad de undefined? Si solo quieres asignar cuando el objeto padre existe, escríbelo de forma explícita:

index.js
Output
Click Run to see the output here.

Cuándo usarlo (y cuándo no)

El operador ?. brilla cuando un valor es legítimamente opcional:

  • Respuestas de API donde ciertos campos pueden venir o no.
  • Consultas al DOM: document.querySelector(".banner")?.remove().
  • Callbacks que quizá no se pasen: options.onError?.(err).
  • Cadenas de llamadas a librerías donde un resultado intermedio puede ser null.

No es la herramienta adecuada cuando el valor siempre debería existir. Llenar el código de ?. para callar errores en esos casos transforma un bug ruidoso y fácil de localizar ("TypeError en la línea 42") en uno silencioso (una variable que aparece como undefined tres funciones más adelante, sin explicación). Si algo tiene que estar ahí, deja que reviente: el stack trace te está haciendo un favor.

Un ejemplo realista

Extraer un valor de una respuesta de API que podría venir incompleta:

index.js
Output
Click Run to see the output here.

Cada ?. se encarga de un nivel de incertidumbre. avatarUrl termina como undefined sin drama. Y onClick?.() llama al handler solo si existe.

Te habrás fijado en el ?? de la línea del displayName: esa es la otra mitad del patrón. ?. te devuelve undefined cuando algo no está; ?? te deja poner un valor por defecto sin tropezar con valores falsy legítimos como 0 o "".

Lo que sigue: Nullish Coalescing

?. y ?? son la misma idea aplicada a problemas distintos: ambos tratan null y undefined como "ausente" y dejan en paz al resto de valores falsy. A continuación veremos cómo ?? te da valores por defecto que tienen sentido, y por qué || lleva años haciendo eso mal sin que nadie se diera cuenta.

Preguntas frecuentes

¿Qué hace el operador ?. en JavaScript?

El operador ?. accede a una propiedad, índice de array o método solo si el valor que tiene delante no es null ni undefined. Si lo es, la expresión completa hace cortocircuito y devuelve undefined en lugar de lanzar un error. Por ejemplo, user?.address?.city no revienta aunque falten user o address.

¿Cuándo conviene usar optional chaining?

Cuando un valor legítimamente puede no estar ahí: respuestas de una API con campos opcionales, búsquedas en el DOM que quizá no encuentren el nodo, callbacks que pueden pasarse o no. Lo que no debes hacer es usar ?. para tapar bugs en los que ese valor debería existir siempre; en esos casos, que falte es información valiosa que te interesa ver (y no silenciar).

¿Qué diferencia hay entre ?. y &&?

En la mayoría de casos dan el mismo resultado, pero ?. solo hace cortocircuito con null o undefined, mientras que && lo hace con cualquier valor falsy, incluidos 0, '' y false. Ejemplo: obj && obj.count devuelve 0 cuando count vale 0; obj?.count también devuelve 0, pero la cadena solo se corta limpiamente ante valores nullish.

¿Funciona el optional chaining con arrays y funciones?

Sí. arr?.[0] lee un índice del array de forma segura y fn?.() llama a la función solo si existe. Ambos siguen la misma regla: si lo que hay delante de ?. es null o undefined, la expresión se queda en undefined y no se ejecuta nada más.

Aprende a programar con Coddy

COMENZAR