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
Lines changed: 166 additions & 0 deletions
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.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)