Pendant vingt ans, la valeur de repli en JavaScript s'écrivait avec deux barres verticales. Ça marchait, sauf quand la donnée valait zéro, une chaîne vide ou false, c'est-à-dire précisément dans les cas qui comptent.
Définition
La coalescence des nuls, écrite avec deux points d'interrogation, renvoie l'opérande de gauche sauf s'il vaut null ou undefined : dans ce cas seulement, elle renvoie celui de droite.
console.log(null ?? "secours"); // "secours"
console.log(undefined ?? "secours"); // "secours"
console.log(0 ?? "secours"); // 0
console.log("" ?? "secours"); // ""
console.log(false ?? "secours"); // falseLes trois dernières lignes résument tout l'intérêt de l'opérateur. Le zéro, la chaîne vide et false sont des réponses valides, et il les laisse passer intactes.
La différence avec ||, en une comparaison
L'ancien opérateur ne teste pas le vide, il teste la véracité. Il remplace donc les huit valeurs décrites dans Truthy et falsy, pas seulement les deux valeurs vides.
| Valeur testée | Avec ?? | Avec || |
|---|---|---|
null | Le repli | Le repli |
undefined | Le repli | Le repli |
0 | 0 | Le repli |
"" | "" | Le repli |
false | false | Le repli |
Les trois dernières lignes sont autant de bugs en puissance : une quantité de zéro affichée comme non renseignée, un commentaire volontairement vide remplacé par un texte par défaut, une case décochée qui se recoche toute seule.
Il reste des cas où || est le bon choix, quand une chaîne vide doit effectivement être traitée comme absente. Un titre saisi mais laissé vide mérite souvent un repli. La question à se poser est simple : le zéro et la chaîne vide sont-ils des réponses légitimes ici ?
Deux règles de syntaxe à connaître
La première est une contrainte du langage, la seconde une commodité arrivée un peu plus tard.
const a = null, b = "valeur", c = "repli";
// Interdit : mélange sans parenthèses avec || ou &&
// const x = a ?? b || c; // SyntaxError
console.log((a ?? b) || c); // "valeur"
// Affectation conditionnelle : ne remplit que si vide
const options = { limite: 0 };
options.limite ??= 50;
options.page ??= 1;
console.log(options); // { limite: 0, page: 1 }Le refus de mélanger sans parenthèses est délibéré : la priorité entre les deux opérateurs n'a rien d'évident, et le comité de normalisation a préféré une erreur claire à une ambiguïté silencieuse. La seconde forme, avec le signe égal, est très pratique pour compléter un objet d'options sans écraser ce que l'appelant a fourni.
Questions fréquentes
Quand faut-il préférer ?? à || ?
Dès que la valeur testée peut légitimement valoir zéro, une chaîne vide ou false. C'est le cas de la plupart des données chiffrées, des champs de texte facultatifs et des préférences booléennes. En cas de doute, ?? est le choix le plus sûr, car il n'agit que sur le vide réel.
Fonctionne-t-il avec le chaînage optionnel ?
Oui, et les deux se combinent très naturellement. Le Chaînage optionnel (?.) évite le plantage à la lecture, l'opérateur ?? fournit ensuite la valeur affichable. L'écriture donnees?.total ?? 0 est devenue un réflexe dès qu'on manipule une réponse d'API.
Est-il disponible partout ?
Il est arrivé dans la norme en 2020 et il est pris en charge par tous les navigateurs actuels ainsi que par Node.js. Sur un projet qui doit viser des environnements plus anciens, l'outil de compilation le transforme automatiquement en une écriture équivalente compatible.