Chaînage optionnel (optional chaining)

Cette fonction est expérimentale
Puisque cette fonction est toujours en développement dans certains navigateurs, veuillez consulter le tableau de compatibilité pour les préfixes à utiliser selon les navigateurs.
Il convient de noter qu'une fonctionnalité expérimentale peut voir sa syntaxe ou son comportement modifié dans le futur en fonction des évolutions de la spécification.

L'opérateur de chaînage optionnel ?. permet de lire la valeur d'une propriété située profondément dans une chaîne d'objets connectés sans avoir à valider expressément que chaque référence dans la chaîne est valide. L'opérateur ?. fonctionne de manière similaire à l'opérateur de chaînage ., à ceci près qu'au lieu de causer une erreur si une référence est null ou undefined, l'expression se court-circuite avec undefined pour valeur de retour. Quand il est utilisé avec des appels de fonctions, il retourne undefined si la fonction donnée n'existe pas.

Celà résulte en des expressions plus courtes et plus simples lors de l'accès à des propriétés chaînées quand il est possible qu'une référence soit manquante. Ceci peut aussi être utile lors de l'exploration du contenu d'un objet lorsqu'il n'y a aucune garantie concernant les propriétés qui sont requises.

Avertissement ! En août 2019, il n'est aucun environnement qui implante nativement cette fonctionnalité. Si vous utilisez Babel, vous devez utiliser ce module pour émuler le chaînage optionnel.

Syntaxe

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

Description

L'opérateur de chaînage optionnel fournit un moyen de simplifier l'accès aux valeurs au sein d'objets connectés quand il est possible qu'une référence ou une fonction soit undefined ou null.

Par exemple, considérant un objet obj qui a une structure imbriquée. Sans chaînage optionnel, chercher une sous-propriété imbriquée en profondeur requiert de valider les références intermédiaires, tel que :

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

La valeur de obj.premier est confirmée comme n'étant pas null (ni undefined) avant que d'accéder à la valeur de obj.premier.second. Ceci prévient l'erreur qui pourrait survenir si vous accédiez simplement obj.premier.second directement sans vérifier obj.premier.

Avec l'opérateur de chaînage optionnel (?.), vous n'avez pas besoin de vérifier explicitement et de court-circuiter la vérification selon l'état de obj.premier avant que d'accéder à obj.premier.second:

let nestedProp = obj.premier?.second;

En utilisant l'opérateur ?. au lieu de l'opérateur ., JavaScript sait implicitement qu'il doit vérifier obj.premier pour être certain qu'il ne soit null ou undefined avant que de tenter d'accéder à obj.first.second. Si obj.premier est null ou undefined, l'expression se court-circuite automatiquement et retourne undefined.

C'est équivalent à :

let nestedProp = (obj.premier== null ? undefined : obj.premier.second);

Chaînage optionnel avec des appels de fonctions

Vous pouvez utiliser le chaînage optionnel lorsque vous tentez d'appeler une méthode qui pourrait ne pas exister. Ceci peut être une aide précieuse, par exemple, lorsque vous utilisez une API dans laquelle une méthode pourrait être indisponible, à cause d'une implantation datée ou à cause d'une fonctionnalité qui n'est pas disponible sur l'appareil de l'utilisateur.

Utiliser le chaînage optionnel avec les appels de fonction entraîne le retour automatique de la valeur undefined pour l'expression plutôt que de jeter une exception si la méthode n'est pas trouvée :

let result = someInterface.customMethod?.();

Note : S'il est une propriété avec un tel nom et qui n'est pas une fonction, utiliser ?. jètera aussi une exception TypeError (x.y is not a function).

Réaliser des fonctions de rappel optionnelles ou des écouteurs d'événements

Si vous utilisez des fonctions ou des méthodes de recherche depuis un objet avec une affectation par décomposition, vous pourriez avoir des valeurs inexistantes que vous ne pouvez appeler comme fonction à moins que vous ayez vérifié leur existance. En utilisant ?., vous pourriez vous passer de cette vérification supplémentaire :

// ES2019
function doSomething (onContent, onError) {
  try {
    // ... travailler avec les données
  }
  catch (err) {
    if (onError) { // vérifier que onError existe réellement
      onError(err.message);
    }
  }
}
// Utiliser le chaînage optionnel avec les appels de fonctions
function doSomething (onContent, onError) {
  try {
   // ... travailler avec les données
  }
  catch (err) {
    onError?.(err.message); // nulle exception si onError est égal à undefined
  }
}

Chaînage optionnel avec les expressions

Vous pouvez aussi utiliser l'opérateur de chaînage optionnel lorsque vous accédez aux propriétés avec une expression en utilisant la notation avec crochets des accesseurs de propriétés :

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

Exemples

Exemple basique

Cet exemple cherche la valeur de la propriété name dans un objet stoké comme propriété de nom bar d'un objet Map alors que cet objet bar n'existe pas. Le résultat est donc undefined.

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

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

Court-circuiter une évaluation

Lorsque vous utilisez le chaînage optionnel avec une expression, si l'opérande gauche est null ou undefined, l'expression ne sera par évaluée. Par exemple :

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

console.log(x); // 0 car x n'a pas été incrémenté

Empiler les opérateurs de chaînage optionnel

Avec les structures imbriquées, il est possible d'utiliser le chaînage optionnel plusieurs fois :

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

// … celà fonctionne aussi avec le chaînage optionnel sur les appel de fonction
let duration = vacations.trip?.getTime?.();

Spécifications

Specification Status Comment
Proposal for the "optional chaining" operator Stage 3

Compatibilité des navigateurs

Update compatibility data on GitHub
OrdinateurMobileServeur
ChromeEdgeFirefoxInternet ExplorerOperaSafariWebview AndroidChrome pour AndroidFirefox pour AndroidOpera pour AndroidSafari sur iOSSamsung InternetNode.js
Optional chaining operator (?.)
Expérimentale
Chrome Support complet 78
Désactivée
Support complet 78
Désactivée
Désactivée From version 78: this feature is behind the Experimental JavaScript preference (needs to be set to true). To change preferences in Chrome, visit chrome://flags.
Edge Aucun support NonFirefox Aucun support NonIE Aucun support NonOpera Support complet 65
Désactivée
Support complet 65
Désactivée
Désactivée From version 65: this feature is behind the Experimental JavaScript preference (needs to be set to true).
Safari Aucun support NonWebView Android Aucun support NonChrome Android Support complet 78
Désactivée
Support complet 78
Désactivée
Désactivée From version 78: this feature is behind the Experimental JavaScript preference (needs to be set to true). To change preferences in Chrome, visit chrome://flags.
Firefox Android Aucun support NonOpera Android Aucun support NonSafari iOS Aucun support NonSamsung Internet Android Aucun support Nonnodejs Aucun support Non

Légende

Support complet  
Support complet
Aucun support  
Aucun support
Fonctionnalité expérimentale. Celle-ci peut être amenée à changer par la suite.
Fonctionnalité expérimentale. Celle-ci peut être amenée à changer par la suite.
Une action explicite de l'utilisateur est nécessaire pour activer cette fonctionnalité.
Une action explicite de l'utilisateur est nécessaire pour activer cette fonctionnalité.

Voir aussi