Skip to content

Commit 584c36f

Browse files
authored
Merge pull request #122 from kiniggit/12-nullish-coalescing-operator
adding new article 12-nullish-coalescing-operator
2 parents 99fc7bb + 1a4399f commit 584c36f

File tree

1 file changed

+117
-0
lines changed
  • 1-js/02-first-steps/12-nullish-coalescing-operator

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Nullish coalescing operator '??'
2+
3+
[recent browser="new"]
4+
5+
The nullish coalescing operator `??` provides a short syntax for selecting a first "defined" variable from the list.
6+
7+
The result of `a ?? b` is:
8+
- `a` if it's not `null` or `undefined`,
9+
- `b`, otherwise.
10+
11+
So, `x = a ?? b` is a short equivalent to:
12+
13+
```js
14+
x = (a !== null && a !== undefined) ? a : b;
15+
```
16+
17+
Here's a longer example.
18+
19+
Let's say, we have a `firstName`, `lastName` or `nickName`, all of them optional.
20+
21+
Let's choose the defined one and show it (or "Anonymous" if nothing is set):
22+
23+
```js run
24+
let firstName = null;
25+
let lastName = null;
26+
let nickName = "Supercoder";
27+
28+
// show the first not-null/undefined variable
29+
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
30+
```
31+
32+
## Comparison with ||
33+
34+
That's very similar to OR `||` operator. Actually, we can replace `??` with `||` in the code above and get the same result.
35+
36+
The important difference is that:
37+
- `||` returns the first *truthy* value.
38+
- `??` returns the first *defined* value.
39+
40+
This matters a lot when we'd like to treat `null/undefined` differently from `0`.
41+
42+
For example:
43+
44+
```js
45+
height = height ?? 100;
46+
```
47+
48+
This sets `height` to `100` if it's not defined. But if `height` is `0`, then it remains "as is".
49+
50+
Let's compare it with `||`:
51+
52+
```js run
53+
let height = 0;
54+
55+
alert(height || 100); // 100
56+
alert(height ?? 100); // 0
57+
```
58+
59+
Here, `height || 100` treats zero height as unset, same as `null`, `undefined` or any other falsy value, depeding on use cases that may be incorrect.
60+
61+
The `height ?? 100` returns `100` only if `height` is exactly `null` or `undefined`.
62+
63+
## Precedence
64+
65+
The precedence of the `??` operator is rather low: `7` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table).
66+
67+
That's lower than most operators and a bit higher than `=` and `?`.
68+
69+
So if we need to use `??` in a complex expression, then consider adding parentheses:
70+
71+
```js run
72+
let height = null;
73+
let width = null;
74+
75+
// important: use parentheses
76+
let area = (height ?? 100) * (width ?? 50);
77+
78+
alert(area); // 5000
79+
```
80+
81+
Otherwise, if we omit parentheses, then `*` has the higher precedence and would run first. That would be the same as:
82+
83+
```js
84+
// not correct
85+
let area = height ?? (100 * width) ?? 50;
86+
```
87+
88+
There's also a related language-level limitation. Due to safety reasons, it's forbidden to use `??` together with `&&` and `||` operators.
89+
90+
The code below triggers a syntax error:
91+
92+
```js run
93+
let x = 1 && 2 ?? 3; // Syntax error
94+
```
95+
96+
The limitation is surely debatable, but for some reason it was added to the language specification.
97+
98+
Use explicit parentheses to fix it:
99+
100+
```js run
101+
let x = (1 && 2) ?? 3; // Works
102+
alert(x); // 2
103+
```
104+
105+
## Summary
106+
107+
- The nullish coalescing operator `??` provides a short way to choose a "defined" value from the list.
108+
109+
It's used to assign default values to variables:
110+
111+
```js
112+
// set height=100, if height is null or undefined
113+
height = height ?? 100;
114+
```
115+
116+
- The operator `??` has a very low precedence, a bit higher than `?` and `=`.
117+
- It's forbidden to use it with `||` or `&&` without explicit parentheses.

0 commit comments

Comments
 (0)