[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/javascript-tutorial/fr.javascript.info/sync-e2f9e584/%3D [Back]  [Original]


# Chanage optionnel '?.'

[recent browser="new"]


Le chanage optionnel `?.` Est un moyen scuris d'accder aux proprits d'objet imbriques, mme si une proprit intermdiaire n'existe pas.

## Le problme de la "proprit non existante"


Si vous venez de commencer  lire le tutoriel et  apprendre JavaScript, peut-tre que le problme ne vous a pas encore touch, mais c'est assez courant.


 titre d'exemple, disons que nous avons des objets `user` qui contiennent les informations sur nos utilisateurs.

La plupart de nos utilisateurs ont des adresses dans la proprit `user.address`, avec la rue `user.address.street`, mais certains ne les ont pas fournies.

Dans ce cas, lorsque nous essayons d'obtenir `user.address.street`, et que l'utilisateur se trouve sans adresse, nous obtenons une erreur :

```js run
let user = {}; // un utilisateur sans proprit "address"


alert(user.address.street); // Error!
```

C'est le rsultat attendu. JavaScript fonctionne comme a. Comme `user.address` est `undefined`, une tentative d'obtention de `user.address.street` choue avec une erreur.

Dans de nombreux cas pratiques, nous prfrerions obtenir `undefined` au lieu d'une erreur ici (signifiant "pas de rue").

... Et un autre exemple. Dans le dveloppement Web, nous pouvons obtenir un objet qui correspond  un lment de page Web  l'aide d'un appel de mthode spcial, tel que `document.querySelector('.elem')`, et il renvoie `null` lorsqu'il n'y a pas ce type d'lment.

```js run
// document.querySelector('.elem') est nul s'il n'y a pas d'lment
let html = document.querySelector('.elem').innerHTML; // error if it's null
```

Encore une fois, si l'lment n'existe pas, nous obtiendrons une erreur lors de l'accs  `.innerHTML` de` null`. Et dans certains cas, lorsque l'absence de l'lment est normale, nous aimerions viter l'erreur et accepter simplement `html = null` comme rsultat.

Comment peut-on le faire ?

La solution vidente serait de vrifier la valeur en utilisant `if` ou l'oprateur conditionnel `?`, Avant d'accder  sa proprit, comme ceci :

```js
let user = {};

alert(user.address ? user.address.street : undefined);
```

Cela fonctionne, il n'y a pas d'erreur ... Mais c'est assez inlgant. Comme vous pouvez le voir, `"user.address"` apparat deux fois dans le code. Pour des proprits plus profondment imbriques, cela devient un problme car plus de rptitions sont ncessaires.

Par exemple. essayons d'obtenir `user.address.street.name`.

Nous devons vrifier  la fois `user.address` et `user.address.street` :

```js
let user = {}; // l'utilisateur n'a pas d'adresse

alert(user.address ? user.address.street ? user.address.street.name : null : null);
```

C'est juste horrible, on peut mme avoir des problmes pour comprendre un tel code.

Ne vous en souciez mme pas, car il existe une meilleure faon de l'crire, en utilisant l'oprateur `&&` :

```js run
let user = {}; // l'utilisateur n'a pas d'adresse

alert( user.address && user.address.street && user.address.street.name ); // undefined (no error)
```

Et le chemin complet vers la proprit garantit que tous les composants existent (sinon, l'valuation s'arrte), mais n'est pas non plus idal.

Comme vous pouvez le voir, les noms de proprits sont toujours dupliqus dans le code. Par exemple. dans le code ci-dessus, `user.address` apparat trois fois.

C'est pourquoi le chanage facultatif `?.` A t ajout au langage. Pour rsoudre ce problme une fois pour toutes !

ET l'ensemble du chemin d'accs  la proprit garantit que tous les composants existent (sinon, l'valuation s'arrte), mais est difficile  crire.


## Chanage optionnel

Le chanage facultatif `?.` arrte l'valuation et renvoie `undefined` si la partie avant `?.` est `undefined` ou `null` et renvoie cette partie.

**Plus loin dans cet article, par souci de brivet, nous dirons que quelque chose "existe" si ce n'est pas "null" et non "undefined".**

En d'autres termes, `value?.prop` :
- est identique  `value.prop` si `value` existe,
- sinon (lorsque `value` est `undefined/nul`), il renvoie `undefined`.

Voici le moyen sr d'accder  `user.address.street` en utilisant `?.` :

```js run
let user = {}; // l'utilisateur n'a pas d'adresse

alert( user?.address?.street ); // undefined (no error)
```

Le code est court et propre, il n'y a aucune duplication.

La lecture de l'adresse avec `user?.address` fonctionne mme si l'objet `user` n'existe pas :

```js run
let user = null;

alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
```

Remarque: la syntaxe `?.` Rend facultative la valeur qui la prcde, mais pas plus.

Par exemple. dans `user?.address.street.name` le `?.` permet  `user` d'tre `null/undefined`, mais c'est tout ce qu'il fait. D'autres proprits sont accessibles de manire rgulire. Si nous voulons que certains d'entre eux soient optionnels, alors nous devrons remplacer plus de `.` par `?.`.

```warn header="N'abusez pas du chanage optionnel"
Nous ne devrions utiliser `?.` que l o il est normal que quelque chose n'existe pas.

Par exemple, si selon notre logique de codage, l'objet `user` doit exister, mais que `address` est facultatif, alors nous devrions crire `user.address?.street`, mais pas `user?.address?.street`.

```

````warn header="La variable avant `?.` doit tre dclare"
S'il n'y a pas du tout de variable `user`, alors `user?.anything` dclenche une erreur :

```js run
// ReferenceError: user is not defined
user?.address;
```
La variable doit tre dclare (par exemple `let/const/var user` ou en tant que paramtre de fonction). Le chanage facultatif ne fonctionne que pour les variables dclares.
````

## Court-circuit

Comme il a t dit prcdemment, le `?.` arrte immdiatement ("court-circuite") l'valuation si la partie gauche n'existe pas.


Donc, s'il y a d'autres appels de fonction ou effets secondaires, ils ne se produisent pas :

Par exemple :

```js run
let user = null;
let x = 0;


user?.sayHi(x++); // pas de "sayHi", donc l'excution n'atteint pas x++


alert(x); // 0, la valeur n'est pas incrment
```


## Autres variantes : ?.(), ?.[]

`?.` n'est pas un oprateur, mais une construction syntaxique particulire qui fonctionne aussi avec les appels de fonction et les crochets.

Par exemple, `?.()` est utilis pour excuter une fonction seulement si elle existe.

Ainsi dans cet exemple la mthode `admin` n'existe pas pour tout le monde :

```js run
let userAdmin = {
  admin() {
    alert("I am admin");
  }
};

let userGuest = {};

*!*
userAdmin.admin?.(); // I am admin
*/!*

*!*
userGuest.admin?.(); // nothing (no such method)
*/!*
```


Ici, dans les deux lignes, nous utilisons d'abord le point (`user1.admin`) pour obtenir la proprit `admin`, car l'objet utilisateur doit exister, donc il peut tre lu en toute scurit.
Puis `?.()` Vrifie la partie gauche : si la fonction admin existe, alors elle s'excute (c'est le cas pour `user1`). Sinon (pour `user2`) l'valuation s'arrte sans erreur.


La syntaxe `?.[]` Fonctionne galement, si nous voulons utiliser des crochets `[]` pour accder aux proprits au lieu du point `.`. Similaire aux cas prcdents, il permet de lire en toute scurit une proprit  partir d'un objet qui peut ne pas exister.

```js run
let user1 = {
  firstName: "John"
};

let user2 = null; // Imaginez, nous ne pouvons pas autoriser l'utilisateur

let key = "firstName";

alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined

alert( user1?.[key]?.something?.not?.existing); // undefined
```

Nous pouvons galement utiliser `?.` avec `delete` :

```js run
delete user?.name; // supprime user.name si user existe
```


```warn header="Nous pouvons utiliser `?.` pour lire et supprimer en toute scurit, mais pas pour crire"
Le chanage optionnel `?.` n'a aucune utilit sur le ct gauche d'une affectation :


For example:
```js run

let user = null;

user?.name = "John"; // Erreur, ne fonctionne pas
// car il value  undefined = "John"
```
Ce n'est tout simplement pas si intelligent.

## Rsum

Le chanage optionnel '?.' A trois formes :

1. `obj?.prop` -- retourne `obj.prop` si `obj` existe, sinon `undefined`.
2. `obj?.[prop]` -- retourne `obj[prop]` si `obj` existe, sinon `undefined`.
3. `obj?.method()` -- appel `obj.method()` si `obj.method` existe, sinon retourne `undefined`.


Comme nous pouvons le voir, tous sont simples et simples  utiliser. Le `?.` vrifie la partie gauche pour `nul/undefined` et permet  l'valuation de se poursuivre si ce n'est pas le cas.

Une chane de `?.` permet d'accder en toute scurit aux proprits imbriques.


Nanmoins, nous devons appliquer ?. Avec soin, uniquement s'il est acceptable que la partie gauche n'existe pas. Pour ne pas nous cacher les erreurs de programmation, si elles se produisent.


Web Proxy Viewer  |  New URL  |  Original Page