Une donnée arrive d'une API, on lit trois propriétés d'affilée, et la page devient blanche. Le message est toujours le même : impossible de lire une propriété de undefined. Un point d'interrogation bien placé règle le problème.
Définition
Le chaînage optionnel, écrit avec un point d'interrogation suivi d'un point, lit une propriété seulement si la valeur de gauche n'est ni null ni undefined. Sinon, il arrête l'évaluation sur-le-champ et renvoie undefined.
const client = { profil: { ville: "Lyon" } };
console.log(client.profil.ville); // "Lyon"
console.log(client.compte?.iban); // undefined, aucune erreur
// Sans l'opérateur, la ligne ci-dessus lèverait :
// TypeError: Cannot read properties of undefinedLe point important tient dans le mot arrêter. Dès qu'une valeur vide est rencontrée, tout le reste de la chaîne est ignoré, même si elle compte encore cinq niveaux. C'est ce qu'on appelle un court-circuit.
Trois formes, pas une seule
L'opérateur ne sert pas qu'aux propriétés nommées. Il se décline pour les indices et pour les appels de fonction, ce que beaucoup ignorent.
| Écriture | Ce qu'elle protège |
|---|---|
objet?.propriete | La lecture d'une propriété |
tableau?.[0] | L'accès par indice ou par clé calculée |
fonction?.() | L'appel, si la fonction n'existe pas |
La troisième forme rend un vrai service sur les fonctions de rappel facultatives : onSucces?.() appelle la fonction si elle a été fournie, et ne fait rien sinon. Plus besoin d'entourer l'appel d'une condition.
L'opérateur ne fonctionne qu'en lecture. Une écriture comme objet?.champ = 1 est refusée par le moteur, avec une erreur de syntaxe. Pour écrire, il faut d'abord garantir que l'objet existe.
Ce qu'il ne fait pas
C'est le point le plus mal compris, et celui qui produit les bugs les plus discrets. L'opérateur protège contre une valeur vide, pas contre une erreur de frappe.
const client = { profil: { ville: "Lyon" } };
console.log(client.profl?.ville); // undefined, et aucune alerteLa propriété est mal orthographiée, la chaîne renvoie undefined, et le programme continue comme si de rien n'était. Sans l'opérateur, la même faute aurait provoqué une erreur immédiate, donc visible. En posant un point d'interrogation, vous échangez un plantage bruyant contre un résultat silencieusement faux.
La règle pratique : ne l'utilisez que là où le vide est un cas normal, prévu par le scénario. Sur une donnée qui doit toujours être là, laissez l'erreur se produire.
Questions fréquentes
Faut-il un point d'interrogation à chaque niveau ?
Non, un seul suffit à l'endroit où le vide est possible. Comme l'évaluation s'arrête au premier maillon vide, écrire a?.b?.c?.d quand seul b peut manquer alourdit le code sans rien apporter. Placez l'opérateur sur le maillon incertain, pas sur toute la chaîne.
Comment lui associer une valeur de repli ?
Avec la Coalescence des nuls (??), qui est son compagnon naturel. L'écriture client.profil?.ville ?? "non renseignée" couvre les deux besoins : la lecture ne plante pas, et l'absence produit une valeur affichable plutôt qu'un undefined visible à l'écran.
Ralentit-il l'exécution ?
Non, l'impact est négligeable, et il est même parfois positif puisque l'évaluation s'arrête plus tôt. Le vrai coût est ailleurs : sur des données extérieures profondément imbriquées, il masque des problèmes de structure. Notre formation Node.js montre comment valider une réponse d'API à l'entrée, ce qui vaut mieux que de la protéger à chaque lecture.