Alexandre CANTIN - Blog personnel

01 avr. 2020

L'opérateur ?? ('null coalescing') en JavaScript

Les limites du ‘OU logique’

L’opérateur || (alias OU logique) en Javascript est bien connu pour la mise en place d’une valeur par défaut, tout en permettant une syntaxe concise.

Ce système nous permet par exemple de définir des valeurs de configuration par défaut, pratique pour dissocier notre environnement de développement avec ceux de recette et production :

  function computeDatabaseUrl() {
    const databaseName = process.env.DATABASE_NAME || 'dev_dv';
    const domainUrl = process.env.DATABASE_DOMAIN || 'localhost';
    const port = process.env.DATABASE_PORT || '10027';

    return `mongodb://${domainUrl}:${port}/${databaseName}';
  }

Toutefois, cet opérateur se basant sur le caractère falsy des valeurs, certains cas spécifiques sont à considérer dont notamment :

  • le chiffre 0
  • la chaîne vide : '' ou ''
  • NaN

Ainsi, dans ces cas précis, notre valeur par défaut sera utilisé… Et, bien que cela puisse être volontaire de notre part, il est possible que cela soit un effet de bord non désirable, un bug en somme !

Pour simplifier, voici une implémentation du OU logique en JavaScript :

function OR(value, defaultValue) {
  if (!value) return defaultValue;
  return value;
}

console.log(OR(1, "default")); // 1
console.log(OR(null, "default")); // 'default'
console.log(OR(undefined, "default")); // 'default'
console.log(OR(false, "default")); // 'default'
console.log(OR(0, "default")); // 'default'
console.log(OR(NaN, "default")); // 'default'
console.log(OR("", "default")); // 'default'
console.log(OR("", "default")); // 'default'
console.log(OR("Bonjour", "default")); // 'Bonjour'

L’arrivée de l’opérateur ?? (“null coalescing”)

Pour pallier à ce souci, l’opérateur ?? fut proposé afin d’enrichir Javascript. Cette proposition est actuellement en stage 3 sur 4 et peut-être consulté à l’adresse suivante : https://github.com/tc39/proposal-nullish-coalescing

Le but de cet opérateur est simple : la valeur par défaut sera prise en compte uniquement si la valeur à analyser est null ou undefined. Fini les effets de bord non désirés !

const entry = null;
const value = entry ?? "Default"; // value => 'Default'

Pour mieux comprendre son fonctionnement, nous pouvons créer un polyfill via l’implémentation suivante :

function nullCoalescing(value, defaultValue) {
  if (value === null || value === undefined) return defaultValue;
  return value;
}

console.log(nullCoalescing(1, "default")); // 1
console.log(nullCoalescing(false, "default")); // 1
console.log(nullCoalescing(0, "default")); // 'default'
console.log(nullCoalescing(NaN, "default")); // 'default'
console.log(nullCoalescing("", "default")); // 'default'
console.log(nullCoalescing("", "default")); // 'default'
console.log(nullCoalescing("Bonjour", "default")); // 'Bonjour'

Malheureusement, cet opérateur n’est pas encore disponible dans les navigateurs, même dans les navigateurs les plus modernes, mais un polyfill existe.

Pour l’utiliser, il faut tout d’abord installer le package : npm install --save-dev @babel/plugin-proposal-nullish-coalescing-operator.

Et, dans un second temps, activer le plugin dans notre configuration Babel (.babelrc) : "plugins": ["@babel/plugin-proposal-nullish-coalescing-operator"]

Plus d’excuse pour ne pas l’utiliser dorénavant ;)

Pour aller plus loin