Skip to content

Commit 81b6c60

Browse files
committed
Merge branch 'master' into feature/conditional-branching
2 parents 2ba3186 + 24513db commit 81b6c60

File tree

16 files changed

+166
-0
lines changed

16 files changed

+166
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Nullish coalescing operator '??'
2+
3+
[recent browser="new"]
4+
5+
Here, in this article, we'll say that an expression is "defined" when it's neither `null` nor `undefined`.
6+
7+
The nullish coalescing operator is written as two question marks `??`.
8+
9+
The result of `a ?? b` is:
10+
- if `a` is defined, then `a`,
11+
- if `a` isn't defined, then `b`.
12+
13+
14+
In other words, `??` returns the first argument if it's not `null/undefined`. Otherwise, the second one.
15+
16+
The nullish coalescing operator isn't anything completely new. It's just a nice syntax to get the first "defined" value of the two.
17+
18+
We can rewrite `result = a ?? b` using the operators that we already know, like this:
19+
20+
```js
21+
result = (a !== null && a !== undefined) ? a : b;
22+
```
23+
24+
The common use case for `??` is to provide a default value for a potentially undefined variable.
25+
26+
For example, here we show `Anonymous` if `user` isn't defined:
27+
28+
```js run
29+
let user;
30+
31+
alert(user ?? "Anonymous"); // Anonymous
32+
```
33+
34+
Of course, if `user` had any value except `null/undefined`, then we would see it instead:
35+
36+
```js run
37+
let user = "John";
38+
39+
alert(user ?? "Anonymous"); // John
40+
```
41+
42+
We can also use a sequence of `??` to select the first value from a list that isn't `null/undefined`.
43+
44+
Let's say we have a user's data in variables `firstName`, `lastName` or `nickName`. All of them may be undefined, if the user decided not to enter a value.
45+
46+
We'd like to display the user name using one of these variables, or show "Anonymous" if all of them are undefined.
47+
48+
Let's use the `??` operator for that:
49+
50+
```js run
51+
let firstName = null;
52+
let lastName = null;
53+
let nickName = "Supercoder";
54+
55+
// shows the first defined value:
56+
*!*
57+
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
58+
*/!*
59+
```
60+
61+
## Comparison with ||
62+
63+
The OR `||` operator can be used in the same way as `??`, as it was described in the [previous chapter](info:logical-operators#or-finds-the-first-truthy-value).
64+
65+
For example, in the code above we could replace `??` with `||` and still get the same result:
66+
67+
```js run
68+
let firstName = null;
69+
let lastName = null;
70+
let nickName = "Supercoder";
71+
72+
// shows the first truthy value:
73+
*!*
74+
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
75+
*/!*
76+
```
77+
78+
The OR `||` operator exists since the beginning of JavaScript, so developers were using it for such purposes for a long time.
79+
80+
On the other hand, the nullish coalescing operator `??` was added to JavaScript only recently, and the reason for that was that people weren't quite happy with `||`.
81+
82+
The important difference between them is that:
83+
- `||` returns the first *truthy* value.
84+
- `??` returns the first *defined* value.
85+
86+
In other words, `||` doesn't distinguish between `false`, `0`, an empty string `""` and `null/undefined`. They are all the same -- falsy values. If any of these is the first argument of `||`, then we'll get the second argument as the result.
87+
88+
In practice though, we may want to use default value only when the variable is `null/undefined`. That is, when the value is really unknown/not set.
89+
90+
For example, consider this:
91+
92+
```js run
93+
let height = 0;
94+
95+
alert(height || 100); // 100
96+
alert(height ?? 100); // 0
97+
```
98+
99+
- The `height || 100` checks `height` for being a falsy value, and it really is.
100+
- so the result is the second argument, `100`.
101+
- The `height ?? 100` checks `height` for being `null/undefined`, and it's not,
102+
- so the result is `height` "as is", that is `0`.
103+
104+
If the zero height is a valid value, that shouldn't be replaced with the default, then `??` does just the right thing.
105+
106+
## Precedence
107+
108+
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 before `=` and `?`, but after most other operations, such as `+`, `*`.
109+
110+
So if we'd like to choose a value with `??` in an expression with other operators, consider adding parentheses:
111+
112+
```js run
113+
let height = null;
114+
let width = null;
115+
116+
// important: use parentheses
117+
let area = (height ?? 100) * (width ?? 50);
118+
119+
alert(area); // 5000
120+
```
121+
122+
Otherwise, if we omit parentheses, then as `*` has the higher precedence than `??`, it would execute first, leading to incorrect results.
123+
124+
```js
125+
// without parentheses
126+
let area = height ?? 100 * width ?? 50;
127+
128+
// ...works the same as this (probably not what we want):
129+
let area = height ?? (100 * width) ?? 50;
130+
```
131+
132+
### Using ?? with && or ||
133+
134+
Due to safety reasons, JavaScript forbids using `??` together with `&&` and `||` operators, unless the precedence is explicitly specified with parentheses.
135+
136+
The code below triggers a syntax error:
137+
138+
```js run
139+
let x = 1 && 2 ?? 3; // Syntax error
140+
```
141+
142+
The limitation is surely debatable, but it was added to the language specification with the purpose to avoid programming mistakes, when people start to switch to `??` from `||`.
143+
144+
Use explicit parentheses to work around it:
145+
146+
```js run
147+
*!*
148+
let x = (1 && 2) ?? 3; // Works
149+
*/!*
150+
151+
alert(x); // 2
152+
```
153+
154+
## Summary
155+
156+
- The nullish coalescing operator `??` provides a short way to choose the first "defined" value from a list.
157+
158+
It's used to assign default values to variables:
159+
160+
```js
161+
// set height=100, if height is null or undefined
162+
height = height ?? 100;
163+
```
164+
165+
- The operator `??` has a very low precedence, only a bit higher than `?` and `=`, so consider adding parentheses when using it in an expression.
166+
- It's forbidden to use it with `||` or `&&` without explicit parentheses.

0 commit comments

Comments
 (0)