130 lines
3.7 KiB
Markdown
130 lines
3.7 KiB
Markdown
# Nullish coalescing operator '??'
|
|
|
|
[recent browser="new"]
|
|
|
|
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:
|
|
|
|
```js
|
|
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:
|
|
|
|
```js run
|
|
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](info:logical-operators#or-finds-the-first-truthy-value).
|
|
|
|
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:
|
|
|
|
```js
|
|
height = height ?? 100;
|
|
```
|
|
|
|
This sets `height` to `100` if it's not defined.
|
|
|
|
Let's compare it with `||`:
|
|
|
|
```js run
|
|
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 the result is `100`.
|
|
|
|
The `height ?? 100` returns `100` only if `height` is exactly `null` or `undefined`. So the `alert` shows the height value `0` "as is".
|
|
|
|
Which behavior is better depends on a particular use case. When zero height is a valid value, then `??` is preferrable.
|
|
|
|
## Precedence
|
|
|
|
The precedence of the `??` operator is rather low: `5` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#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:
|
|
|
|
```js run
|
|
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:
|
|
|
|
```js
|
|
// 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:
|
|
|
|
```js run
|
|
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:
|
|
|
|
```js run
|
|
*!*
|
|
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:
|
|
|
|
```js
|
|
// 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.
|