minor fixes

This commit is contained in:
Ilya Kantor 2020-05-31 17:18:07 +03:00
parent 075266e251
commit 69e44506c3

View file

@ -16,22 +16,26 @@ x = (a !== null && a !== undefined) ? a : b;
Here's a longer example.
Let's say, we have a `firstName`, `lastName` or `nickName`, all of them optional.
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.
Let's choose the defined one and show it (or "Anonymous" if nothing is set):
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 variable
// show the first not-null/undefined value
*!*
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
*/!*
```
## Comparison with ||
That's very similar to OR `||` operator. Actually, we can replace `??` with `||` in the code above and get the same result.
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.
@ -39,13 +43,13 @@ The important difference is that:
This matters a lot when we'd like to treat `null/undefined` differently from `0`.
For example:
For example, consider this:
```js
height = height ?? 100;
```
This sets `height` to `100` if it's not defined. But if `height` is `0`, then it remains "as is".
This sets `height` to `100` if it's not defined.
Let's compare it with `||`:
@ -56,17 +60,19 @@ 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, depeding on use cases that may be incorrect.
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`.
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table).
That's lower than most operators and a bit higher than `=` and `?`.
So `??` is evaluated after most other operations, but before `=` and `?`.
So if we need to use `??` in a complex expression, then consider adding parentheses:
If we need to choose a value with `??` in a complex expression, then consider adding parentheses:
```js run
let height = null;
@ -78,14 +84,18 @@ let area = (height ?? 100) * (width ?? 50);
alert(area); // 5000
```
Otherwise, if we omit parentheses, then `*` has the higher precedence and would run first. That would be the same as:
Otherwise, if we omit parentheses, `*` has the higher precedence than `??` and would run first.
That would work be the same as:
```js
// not correct
// 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.
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:
@ -93,12 +103,15 @@ The code below triggers a syntax error:
let x = 1 && 2 ?? 3; // Syntax error
```
The limitation is surely debatable, but for some reason it was added to the language specification.
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 fix it:
Use explicit parentheses to work around it:
```js run
*!*
let x = (1 && 2) ?? 3; // Works
*/!*
alert(x); // 2
```