Encadenamiento opcional

El operador de encadenamiento opcional ?. permite leer el valor de una propiedad ubicada dentro de una cadena de objetos conectados sin tener que validar expresamente que cada referencia en la cadena sea válida. El operador ?. funciona de manera similar a el operador de encadenamiento ., excepto que en lugar de causar un error si una referencia es casi-nula (nullundefined), la expresión hace una evaluación de circuito corto con un valor de retorno de undefined. Cuando se usa con llamadas a funciones, devuelve undefined si la función dada no existe.

Esto da como resultado expresiones más cortas y simples cuando se accede a propiedades encadenadas dónde existe la posibilidad de que falte una referencia. También puede ser útil al explorar el contenido de un objeto cuando no hay una garantía conocida de qué propiedades se requieren.

Sintaxis

obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)

Descripción

El operador de encadenamiento opcional proporciona una forma de simplificar el acceso a los valores a través de objetos conectados cuando es posible que una referencia o función sea undefinednull.

Por ejemplo, considere un objeto obj que tiene una estructura anidada. Sin encadenamiento opcional, buscar una subpropiedad profundamente anidada requiere validar las referencias intermedias, como:

let nestedProp = obj.first && obj.first.second;

Se confirma que el valor de obj.first no es null (y no es undefined) antes de acceder al valor de obj.first.second. Esto evita el error que ocurriría si simplemente accediera a obj.first.second directamente sin probar obj.first.

Sin embargo, con el operador de encadenamiento opcional (?.), No tiene que probar explícitamente, ni realizar una evaluación de circuito corto basada en el estado de obj.first antes de intentar acceder a obj.first.second:

let nestedProp = obj.first?.second;

Al usar el operador ?. en lugar de solo el ., JavaScript sabe verificar implícitamente para asegurarse de que obj.first no es nullundefined antes de intentar acceder  obj.first.second. Si obj.first es nullundefined, la expresión hace una evaluación de circuito corto automáticamente y retorna undefined.

Esto es equivalente a lo siguiente, excepto que la variable temporal es de hecho no creada:

let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);

Encadenamiento opcional con llamadas a funciones

Puede usar el encadenamiento opcional cuando intente llamar a un método que puede no existir. Esto puede ser útil, por ejemplo, cuando se usa una API en la que un método podría no estar disponible, ya sea debido a la antigüedad de la implementación o debido a una característica que no está disponible en el dispositivo del usuario.

El uso de encadenamiento opcional con llamadas a funciones hace que la expresión regrese automáticamente undefined en lugar de lanzar una excepción si no se encuentra el método:

let result = someInterface.customMethod?.();

Nota: Si hay una propiedad con ese nombre y que no es una función, usar ?. aún levantará una excepción TypeError (x.y is not a function).

Manejo de callbacks opcionales o manejadores de eventos

Si utiliza callbacks o métodos de recuperación de un objeto con una asignación de desestructuración, es posible que tenga valores inexistentes que no puede llamar como funciones a menos que haya probado su existencia. Usando ?., Puede evitar esta prueba adicional:

// Escrito a partir de ES2019
function doSomething(onContent, onError) {
  try {
    // ... hacer algo con los datos
  }
  catch (err) {
    if (onError) { // Probando si onError realmente existe
      onError(err.message);
    }
  }
}
// Usando encadenamiento opcional con llamado de funciones
function doSomething(onContent, onError) {
  try {
   // ... hacer algo con los datos
  }
  catch (err) {
    onError?.(err.message); // Sin excepción si onError esta undefined
  }
}

Encadenamiento opcional con expresiones

También puede usar el operador de encadenamiento opcional al acceder a propiedades con una expresión usando la notación de corchetes:

let nestedProp = obj?.['prop' + 'Name'];

El encadenamiento opcional no es válido al lado izquierdo de una asignación

let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment

Acceso a elementos de un arreglo con encadenamiento opcional

let arrayItem = arr?.[42];

Ejemplos

Ejemplo básico

Este ejemplo busca el valor de la propiedad name para el miembro bar en un mapa cuando no existe dicho miembro. El resultado es por lo tanto es undefined.

let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});

let nameBar = myMap.get("bar")?.name;

Evaluación de circuito corto

Cuando se usa el encadenamiento opcional con expresiones, si el operando izquierdo es null o undefined, la expresión no se evaluará. Por ejemplo:

let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];

console.log(x); // 0 como x no se incrementó

Apilando el operador de encadenamiento opcional

Con estructuras anidadas, es posible usar encadenamiento opcional varias veces:

let customer = {
  name: "Carl",
  details: {
    age: 82,
    location: "Paradise Falls" // "detailed address" es desconocida
  }
};
let customerCity = customer.details?.address?.city;

// … esto también funciona con la función opcional de encadenamiento
let duration = vacations.trip?.getTime?.();

Combinando con el operador de fusión nulo

El operador de fusión nulo se puede usar después del encadenamiento opcional para generar un valor predeterminado cuando no se encontró ninguno:

let customer = {
  name: "Carl",
  details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city

Especificaciones

Specification
ECMAScript (ECMA-262)
La definición de 'optional expression' en esta especificación.

Compatibilidad de navegadores

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome para AndroidFirefox para AndroidOpera para AndroidSafari en iOSSamsung InternetNode.js
Optional chaining operator (?.)Chrome Soporte completo 80
Soporte completo 80
Soporte completo 79
Deshabilitado
Deshabilitado From version 79: this feature is behind the Experimental JavaScript preference (needs to be set to true). To change preferences in Chrome, visit chrome://flags.
Edge Soporte completo 80
Soporte completo 80
Soporte completo 79
Deshabilitado
Deshabilitado From version 79: this feature is behind the Experimental JavaScript preference (needs to be set to true).
Firefox Soporte completo 74IE Sin soporte NoOpera Soporte completo 67
Soporte completo 67
Soporte completo 66
Deshabilitado
Deshabilitado From version 66: this feature is behind the Experimental JavaScript preference (needs to be set to true).
Safari Soporte completo 13.1WebView Android Soporte completo 80Chrome Android Soporte completo 80
Soporte completo 80
Soporte completo 79
Deshabilitado
Deshabilitado From version 79: this feature is behind the Experimental JavaScript preference (needs to be set to true). To change preferences in Chrome, visit chrome://flags.
Firefox Android Sin soporte NoOpera Android Sin soporte NoSafari iOS Soporte completo 13.4Samsung Internet Android Sin soporte Nonodejs Soporte completo 14.0.0

Leyenda

Soporte completo  
Soporte completo
Sin soporte  
Sin soporte
El usuario debe de habilitar explícitamente esta característica.
El usuario debe de habilitar explícitamente esta característica.

Progreso de implementación

La siguiente tabla proporciona un estado de implementación diaria para esta característica, porque esta característica aún no ha alcanzado la estabilidad entre navegadores. Los datos se generan ejecutando las pruebas de características relevantes en Test262, el conjunto de pruebas estándar de JavaScript, en la compilación nocturna o la última versión del motor de JavaScript de cada navegador.

Ver también