31st May 2020

Nullish coalescing operator '??'

A recent addition
This is a recent addition to the language. Old browsers may need polyfills.

The nullish coalescing operator ?? provides a short syntax for selecting a first “defined” variable from the list.

The result of a ?? b is:

  • a if it’s not null or undefined,
  • b, otherwise.

So, x = a ?? b is a short equivalent to:

x = (a !== null && a !== undefined) ? a : b;

Here’s a longer example.

Imagine, we have a user, and there are variables firstName, lastName or nickName for their first name, last name and the nick name. All of them may be undefined, if the user decided not to enter any value.

We’d like to display the user name: one of these three variables, or show “Anonymous” if nothing is set.

Let’s use the ?? operator to select the first defined one:

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// show the first not-null/undefined value
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

Comparison with ||

The OR || operator can be used in the same way as ??. Actually, we can replace ?? with || in the code above and get the same result, as it was described in the previous chapter.

The important difference is that:

  • || returns the first truthy value.
  • ?? returns the first defined value.

This matters a lot when we’d like to treat null/undefined differently from 0.

For example, consider this:

height = height ?? 100;

This sets height to 100 if it’s not defined.

Let’s compare it with ||:

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0

Here, height || 100 treats zero height as unset, same as null, undefined or any other falsy value. So zero becames 100.

The height ?? 100 returns 100 only if height is exactly null or undefined. So zero remains “as is”.

Which behavior is better depends on a particular use case. When zero height is a valid value, that we shouldn’t touch, then ?? is preferrable.

Precedence

The precedence of the ?? operator is rather low: 7 in the MDN table.

So ?? is evaluated after most other operations, but before = and ?.

If we need to choose a value with ?? in a complex expression, then consider adding parentheses:

let height = null;
let width = null;

// important: use parentheses
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000

Otherwise, if we omit parentheses, * has the higher precedence than ?? and would run first.

That would work be the same as:

// probably not correct
let area = height ?? (100 * width) ?? 50;

There’s also a related language-level limitation.

Due to safety reasons, it’s forbidden to use ?? together with && and || operators.

The code below triggers a syntax error:

let x = 1 && 2 ?? 3; // Syntax error

The limitation is surely debatable, but it was added to the language specification with the purpose to avoid programming mistakes, as people start to switch to ?? from ||.

Use explicit parentheses to work around it:

let x = (1 && 2) ?? 3; // Works

alert(x); // 2

Summary

  • The nullish coalescing operator ?? provides a short way to choose a “defined” value from the list.

    It’s used to assign default values to variables:

    // set height=100, if height is null or undefined
    height = height ?? 100;
  • The operator ?? has a very low precedence, a bit higher than ? and =.

  • It’s forbidden to use it with || or && without explicit parentheses.

Tutorial map

Comments

read this before commenting…
  • If you have suggestions what to improve - please submit a GitHub issue or a pull request instead of commenting.
  • If you can't understand something in the article – please elaborate.
  • To insert a few words of code, use the <code> tag, for several lines – use <pre>, for more than 10 lines – use a sandbox (plnkr, JSBin, codepen…)