Apprenez en lisant dans l'ordre

null et undefined — lire en sécurité avec ?. et ??

La différence entre null et undefined, puis lire un objet imbriqué sans erreur et poser un défaut sûr.

En affichant des données de commande d'un serveur, tu vas tomber sur une adresse jamais renseignée, ou un mode de paiement pas encore choisi. JavaScript a deux valeurs pour cet état « rien n'est là » — undefined et null — et une lecture échouée arrête le traitement avec un TypeError.

Cet article couvre la différence entre les deux, la lecture à travers une étape manquante sans s'arrêter, et l'application d'une valeur par défaut quand quelque chose manque.

Les 2 valeurs signifiant que rien n'est là — undefined et null

undefined (une valeur que JavaScript remplit automatiquement quand rien n'a encore été assigné) apparaît de lui-même — tu n'as pas besoin de l'assigner toi-même. Tu l'as déjà vu revenir en lisant au-delà de la fin d'un tableau ou une clé d'objet non enregistrée, et une variable seulement déclarée tombe aussi dans cette catégorie.

  • Une variable seulement déclarée, jamais assignée, comme let couponCode;
  • Une clé non enregistrée sur un objet, comme order.customer (vu plus tôt)
  • Un index hors limites sur un tableau à 2 éléments, comme tags[5] (vu plus tôt)

null (une valeur que l'auteur assigne délibérément pour signaler le vide), en revanche, n'apparaît jamais de lui-même. Quand tu veux que l'absence même d'une valeur soit une donnée — « aucune adresse de livraison choisie pour l'instant », « aucun coupon appliqué » — tu assignes null toi-même.

Le JSON qui revient d'une API peut aussi porter null pour signaler qu'un champ est vide.

Puisque ce sont des valeurs différentes, === renvoie false en les comparant. ==, cependant, traite les deux comme identiques et renvoie true.

Quand tu écris une vérification, soit sois précis sur laquelle des deux tu attends et vérifie juste ce côté, comme dans === null, soit confie ça entièrement à ?. et ??, couverts à partir d'ici.

Qui place undefined et null
Lire une varseulement déclaréeJavaScript laremplitundefinedLire une clé ou unindex manquantJavaScript laremplitundefinedVeut signalerle videL'auteurl'assignenullRempli automatiquementAssigné par l'auteur
Dans les 2 lignes du haut, undefined est une valeur que JavaScript remplit automatiquement ; dans la ligne du bas, null est une valeur que l'auteur assigne.
let couponCode;                 // seulement déclarée, pas de valeur assignée
console.log(couponCode);        // undefined

const order = { orderId: "ORD-1105", total: 12800 };
console.log(order.customer);    // undefined (une clé non enregistrée)

const tags = ["Limité", "Précommande"];
console.log(tags[5]);           // undefined (un index hors limites)

// null est assigné par l'auteur
let shippingAddress = null;     // aucune adresse de livraison choisie pour l'instant
console.log(shippingAddress);   // null

console.log(shippingAddress === undefined);  // false (ce sont des valeurs différentes)
console.log(shippingAddress == undefined);   // true (== les traite comme identiques)

Ne pas s'arrêter quand une étape imbriquée manque — le chaînage optionnel ?.

Les données renvoyées par une API n'ont pas toujours tous les champs remplis. Du code qui lit en profondeur, comme order.customer.address.city, s'arrête dès qu'une seule commande manque d'un address en cours de route.

C'est là que tu veux que la lecture elle-même n'échoue pas — qu'elle continue comme « rien là » à la place.

Quand order.customer.address vaut undefined, essayer de lire .city après ça lève TypeError: Cannot read properties of undefined (reading 'city'). Le 1er niveau de lecture se passe bien, mais ça s'arrête au 2e.

C'est à ça que sert le chaînage optionnel (l'opérateur ?., qui renvoie undefined sans lire plus loin si le côté gauche est null ou undefined). Écris address?.city, et .city ne se lit que quand address a une valeur — sinon, la lecture s'arrête là et renvoie undefined.

Quand tu passes une clé à travers [], écris-la comme ?.[field].

Où ?. arrête de lire
customera une valeur?.addressa une valeur?.cityAustinshippingnull?.carriers'arrête iciundefinedpaymentclé absente?.methods'arrête iciundefined
Là où il y a une valeur, ça continue. Dès que ça touche null, undefined, ou une clé manquante elle-même, ça s'arrête et renvoie undefined sans lire le reste.
const order = {
  orderId: "ORD-1105",
  customer: { name: "Ryan Cole" },
};

// address manque, donc lire city après ça s'arrêterait
// console.log(order.customer.address.city);
// TypeError: Cannot read properties of undefined (reading 'city')

// Insère ?. et la lecture s'arrête, renvoyant undefined
console.log(order.customer.address?.city);   // undefined

// Là où il y a une valeur, ça continue normalement
console.log(order.customer.name);            // Ryan Cole

// Passe une clé à travers une variable avec ?.[]
const field = "city";
console.log(order.customer.address?.[field]);   // undefined

Utilise-le seulement là où un champ peut légitimement manquer

Mets ?. à chaque étape, et même un nom de clé mal orthographié glisse comme undefined sans lever d'erreur. Passe-le sur les champs garantis d'être là, et utilise-le seulement juste avant un champ qui peut légitimement manquer — ainsi les erreurs que tu veux vraiment attraper arrêtent toujours l'exécution.

Lis des valeurs d'un objet ayant la forme d'une réponse d'API de commande, sans t'arrêter quand des champs manquent. response est déjà déclaré, et customer est toujours présent.

① Affiche la ville de livraison, écrite pour ne pas s'arrêter même si quelque chose manque en chemin.

② Affiche le nom du transporteur, shipping.carrier, avec la même syntaxe.

③ Affiche le mode de paiement, payment.method, avec la même syntaxe.

④ Lis un nom de champ depuis une variable, et affiche le code postal de livraison.

(Si tout s'exécute correctement, une explication apparaîtra.)

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Mettre en place une valeur par défaut — ?? vs ||

Plutôt que d'afficher un simple undefined quand un champ manque, tu voudras généralement afficher une valeur par défaut — « Invité », « 20 articles ».

Utilise || pour ça, cependant, et parfois une valeur réellement présente se fait remplacer par la valeur par défaut quand même. Un compte de stock de 0, ou un champ de note vide, en sont des exemples.

null et undefined ensemble s'appellent nullish. Utilise l'opérateur de coalescence des nuls (l'opérateur ??, qui renvoie le côté droit seulement quand le côté gauche est nullish), et 0, une chaîne vide, ou false restent exactement comme ils sont.

|| renvoie le côté droit dès que la gauche est falsy, donc ça ne peut pas distinguer « il n'y a pas de valeur » de « la valeur est 0 ». Quand ton but est d'appliquer une valeur par défaut, ?? évite le remplacement non voulu.

?? et || divergent sur les valeurs falsy
stock vaut 0|| vérifieremplace falsy20remplacéstock vaut 0?? vérifieremplace null seul0inchangéstock vaut null?? vérifieremplace null seul20remplacé
Les résultats ne divergent que quand stock vaut 0. ?? remplace seulement null et undefined, donc 0 reste la valeur.
Valeur à gaucheCe que || renvoieCe que ?? renvoie
nullla valeur par défautla valeur par défaut
undefinedla valeur par défautla valeur par défaut
0la valeur par défautreste 0
chaîne videla valeur par défautreste une chaîne vide
falsela valeur par défautreste false
const settings = { displayName: null, itemsPerPage: 0 };

// ?? renvoie le côté droit seulement quand la gauche est null ou undefined
console.log(settings.displayName ?? "Invité");   // Invité
console.log(settings.itemsPerPage ?? 20);        // 0 (reste tel quel)

// || renvoie le côté droit dès que la gauche est falsy, donc même 0 se fait remplacer
console.log(settings.itemsPerPage || 20);        // 20

// Une clé non enregistrée retombe sur la valeur par défaut dans les deux cas
console.log(settings.language ?? "fr");          // fr
console.log(settings.language || "fr");          // fr

Remarque qu'écrire ?? et || côte à côte sans parenthèses, comme dans displayName ?? "Invité" || "Anonyme", est une erreur de syntaxe — JavaScript ne peut pas décider lequel évaluer en premier. Pour utiliser les deux, sépare-les avec des parenthèses, comme dans (displayName ?? "Invité") || "Anonyme".

Applique une valeur par défaut à chaque champ d'un objet de paramètres utilisateur, en construisant les valeurs que tu vas afficher. Les champs qui ont déjà une valeur doivent rester intacts. userSettings est déjà déclaré.

① Applique une valeur par défaut de « Invité » au nom d'affichage et affiche-le.

② Applique une valeur par défaut de « fr » à la langue d'affichage et affiche-la.

③ Applique une valeur par défaut de 20 au compte d'éléments par page et affiche-le.

④ Applique une valeur par défaut de false au paramètre de notifications non enregistré et affiche-le.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Ne laisse pas une valeur par défaut effacer 0 ou une chaîne vide

Un compte de stock de 0, un taux de réduction de 0, une note vide — tout ça compte comme « il y a une valeur ». Applique une valeur par défaut avec ||, et puisque ce sont des valeurs falsy, elles se font remplacer par la valeur par défaut, créant un décalage comme un article en rupture de stock qui s'affiche comme disponible. Utilise ?? quand tout ce qui t'importe, c'est si une valeur est présente du tout.

Compare comment l'affichage change selon l'opérateur de valeur par défaut que tu utilises, pour un produit avec 0 en stock et une note vide. product est déjà déclaré.

① Applique une valeur par défaut de 10 au compte de stock avec || et affiche-le.

② Applique la même valeur par défaut de 10 au compte de stock avec ?? et affiche-le.

③ Applique une valeur par défaut de « Aucune note » à la note avec ||, entoure-la de crochets, et affiche-la.

④ Applique la même valeur par défaut de « Aucune note » à la note avec ??, entoure-la de crochets, et affiche-la.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Ne pas appeler quelque chose qui n'est pas là — l'appel ?.()

Dans le traitement de commandes, tu vas parfois ranger un « quoi faire en cas de succès » et un « quoi faire en cas d'échec » dans un objet, en les appelant au besoin. Appelle un champ qui n'a rien de configuré, cependant, et ça s'arrête avec TypeError: handlers.onError is not a function — donc tu as besoin d'un moyen de l'appeler seulement quand c'est réellement là.

La fonction couverte dans l'article 3 peut aussi vivre à l'intérieur d'un objet comme valeur d'une propriété. Le () => ... dans l'exemple suivant est une syntaxe pour créer une fonction sur le coup — cette syntaxe elle-même est couverte dans la catégorie syntaxe, donc ici concentre-toi juste sur comment le résultat change selon qu'une fonction est présente dans la propriété.

Appelle une propriété qui pourrait contenir une fonction comme handlers.onError?.(), et quand onError est null ou undefined, l'appel se fait sauter et undefined revient à la place.

?.() saute l'appel quand rien n'est enregistré
onSuccess estune fonctionAppelle avec?.()Ça s'exécuteonErrorest nullAppelle avec?.()Sauté,undefinedonErrorest nullAppeléesans ?.S'arrête avecun TypeError
Appelle-la si une fonction est là ; renvoie undefined sans rien appeler si c'est null. Appelle-la sans ?. et ça s'arrête avec un TypeError.
const handlers = {
  onSuccess: () => console.log("Commande confirmée"),
  onError: null,
};

// Une fonction est là, donc elle se fait appeler
handlers.onSuccess?.();              // Commande confirmée

// C'est null, donc l'appel est sauté et undefined revient
console.log(handlers.onError?.());   // undefined

// Appeler sans ?. arrête l'exécution
// handlers.onError();
// TypeError: handlers.onError is not a function

Compare l'appel avec ?. à l'appel sans, en utilisant un objet qui regroupe des gestionnaires de traitement de commande. handlers est déjà déclaré.

① Appelle le gestionnaire de succès en utilisant une syntaxe qui saute l'appel s'il n'est pas enregistré.

② Appelle le gestionnaire d'échec de la même façon, et affiche ce qui revient.

③ Appelle ce même gestionnaire d'échec sans ?., et vois quel message arrête l'exécution.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Écris let couponCode; et lis-la sans assigner de valeur. Quelle est la valeur de la variable ?

Question 2Quand le côté gauche de ?. est null ou undefined, que se passe-t-il pour le reste de la chaîne ?

Question 3Avec const discountRate = 0;, que renvoient respectivement discountRate || 5 et discountRate ?? 5 ?