W3docs

L'opérateur de coalescence nulle JavaScript (??)

Découvrez l'opérateur de coalescence nulle JavaScript (??), ses différences avec ||, la précédence des opérateurs, et les opérateurs ??=, &&= et ||=.

L'opérateur de coalescence nulle (??) est une façon concise et expressive de fournir une valeur par défaut en JavaScript. Il retourne son opérande de droite uniquement lorsque l'opérande de gauche est nullish — c'est-à-dire null ou undefined — et renvoie sinon la valeur de gauche telle quelle. Introduit dans ES2020, il résout un problème récurrent lié à l'utilisation de l'opérateur || pour les valeurs par défaut, et fonctionne de pair avec le chaînage optionnel et les opérateurs logiques que vous connaissez déjà.

Ce que signifie « nullish »

Une valeur est considérée nullish lorsqu'elle est exactement null ou undefined. Toute autre valeur — y compris les valeurs fausses comme 0, '', false et NaN — est traitée comme une valeur réelle et intentionnelle par ??.

null ?? 'default'       // 'default'
undefined ?? 'default'  // 'default'

0 ?? 'default'          // 0
'' ?? 'default'         // ''
false ?? 'default'      // false
NaN ?? 'default'        // NaN

La règle est simple : si le côté gauche est null ou undefined, vous obtenez le côté droit ; sinon vous obtenez le côté gauche.

javascript— editable

Différences entre ?? et ||

C'est la raison principale pour laquelle ?? existe. L'opérateur OR logique (||) retourne le côté droit dès que le côté gauche est une valeur falsy quelconque — 0, '', false, NaN, null et undefined sont tous concernés. Ce comportement convient jusqu'à ce que 0 ou une chaîne vide soit une valeur légitime, auquel point || produit silencieusement un résultat incorrect.

Considérons un compteur dont la valeur valide peut être 0 :

let count = 0;

let withOr = count || 100;   // 100  — wrong! 0 got replaced
let withNullish = count ?? 100; // 0   — correct, 0 was preserved

Parce que 0 est falsy, || le traite comme « aucune valeur » et bascule vers 100. L'opérateur ?? reconnaît que 0 n'est pas nullish et le conserve. Le même piège s'applique aux chaînes vides :

javascript— editable
Avertissement

Préférez ?? à || chaque fois que 0, '' ou false sont des entrées valides. Utiliser || pour les valeurs par défaut dans ces cas est l'une des sources les plus courantes de bugs subtils en JavaScript — par exemple, une quantité de 0 qui devient 1, ou un champ de recherche vide qui prend une valeur par défaut indésirable.

Précédence et parenthèses

L'opérateur ?? a une faible précédence — environ au même niveau que || et inférieure aux opérateurs arithmétiques et de comparaison. En pratique, cela signifie que la valeur de repli est résolue avant d'être utilisée dans une expression plus grande, mais vous devriez tout de même grouper avec des parenthèses pour garder l'intention claire.

let height = null;
let width;

// Each ?? is evaluated, then the products are multiplied
let area = (height ?? 100) * (width ?? 50);
console.log(area); // 100 * 50 = 5000

Sans les parenthèses, la multiplication se lierait plus étroitement que prévu, donc entourer chaque valeur par défaut avec ( ... ) rend le calcul sans ambiguïté et lisible.

Combiner ?? avec && ou || est interdit

JavaScript refuse délibérément de mélanger ?? avec && ou || dans la même expression sans parenthèses. Cela provoque une SyntaxError, car la précédence entre eux serait ambiguë et facile à mal interpréter.

// SyntaxError: Unexpected token '||'
let result = a ?? b || c;

// Fix it by grouping explicitly:
let safe = (a ?? b) || c;   // valid
let other = a ?? (b || c);  // also valid, different meaning

Les deux formes valides ont des significations différentes, c'est précisément pourquoi le langage vous oblige à choisir. Ajoutez les parenthèses et indiquez précisément ce que vous voulez faire.

Note

La restriction s'applique uniquement lorsque ?? se trouve directement à côté de && ou ||. Vous pouvez les utiliser dans des expressions séparées, et les parenthèses résolvent toujours l'ambiguïté.

Opérateurs d'affectation logique

ES2021 a ajouté trois opérateurs d'affectation logique qui associent une affectation à une vérification logique. Ils n'affectent la variable de gauche que lorsqu'une condition est remplie, ce qui les rend parfaits pour définir des valeurs par défaut et effectuer des mises à jour conditionnelles.

Affectation nullish (??=)

x ??= y affecte y à x uniquement si x est actuellement null ou undefined. C'est la forme d'affectation de ?? et le plus courant des trois pour définir des valeurs par défaut sur un object.

let settings = { theme: 'dark' };

settings.theme ??= 'light';   // already set → stays 'dark'
settings.fontSize ??= 16;     // missing → becomes 16

console.log(settings); // { theme: 'dark', fontSize: 16 }

Affectation OR logique (||=)

x ||= y affecte y à x lorsque x est falsy (0, '', false, null, undefined, NaN). Comme ||, il peut écraser des valeurs falsy valides, donc utilisez-le uniquement lorsqu'une valeur falsy signifie vraiment « remplacez-moi ».

javascript— editable

Affectation AND logique (&&=)

x &&= y affecte y à x uniquement lorsque x est truthy. C'est pratique pour mettre à jour une valeur qui existe déjà sans la créer.

let config = { token: 'abc123' };

config.token &&= config.token.trim(); // truthy → trimmed and reassigned
config.missing &&= 'never set';        // undefined → left untouched

console.log(config); // { token: 'abc123' }

Chaque opérateur effectue également un court-circuit : il n'évalue et n'affecte le côté droit que lorsque la condition l'exige, de sorte que les effets de bord à droite sont ignorés lorsque l'affectation n'a pas lieu.

Cas d'usage concrets

L'opérateur ?? est particulièrement utile partout où une valeur peut légitimement être absente tandis que 0 ou '' doivent être respectés. Les scénarios typiques incluent la lecture de configuration, la définition de valeurs par défaut pour les paramètres de fonction optionnels, et la récupération de champs depuis des réponses API.

// 1. Default options merged with user input
function createButton(options) {
  let label = options.label ?? 'Submit';
  let count = options.count ?? 0; // 0 stays 0, never becomes a default
  return { label, count };
}

// 2. Reading a possibly-missing API field
let response = { data: { user: { nickname: null } } };
let name = response.data.user.nickname ?? 'Guest';
console.log(name); // 'Guest'

Il se marie particulièrement bien avec le chaînage optionnel (?.). Le chaînage optionnel retourne undefined en toute sécurité lorsqu'une partie d'un chemin est manquante, et ?? fournit alors la valeur de repli en une seule ligne claire :

let city = user?.address?.city ?? 'Unknown';

Cela se lit comme : « Utiliser la ville de l'utilisateur si toute la chaîne existe, sinon utiliser 'Unknown'. » Pour décider lequel de deux chemins emprunter selon une condition, l'opérateur conditionnel (ternaire) reste le meilleur outil — ?? est spécifiquement conçu pour fournir des valeurs par défaut aux valeurs nullish.

Info

Compatibilité navigateur : ?? fait partie d'ES2020 et les opérateurs d'affectation logique (??=, ||=, &&=) sont arrivés dans ES2021. Tous les navigateurs modernes et Node.js 14+ les prennent en charge. Si vous devez cibler des environnements très anciens, un transpileur comme Babel peut les compiler.

Résumé

  • ?? retourne l'opérande de droite uniquement lorsque celui de gauche est null ou undefined ; sinon il retourne celui de gauche.
  • Préférez ?? à || pour les valeurs par défaut lorsque 0, '' ou false sont des valeurs valides.
  • ?? a une faible précédence — groupez avec des parenthèses, et ne le placez jamais directement à côté de && ou || sans parenthèses (cela provoque une SyntaxError).
  • ??=, ||= et &&= affectent conditionnellement : sur nullish, sur falsy et sur truthy respectivement.
  • Combinez ?? avec le chaînage optionnel (?.) pour lire des données potentiellement manquantes et leur fournir une valeur par défaut en une seule expression.

Testez vos connaissances

Pratique
Que retourne l'expression 0 ?? 100 ?
Que retourne l'expression 0 ?? 100 ?
Pratique
Pourquoi écrire a ?? b || c sans parenthèses pose-t-il un problème ?
Pourquoi écrire a ?? b || c sans parenthèses pose-t-il un problème ?
Pratique
Que fait user.role ??= 'member' lorsque user.role est undefined ?
Que fait user.role ??= 'member' lorsque user.role est undefined ?
Was this page helpful?