From 69e44506c3e9dac74c282be37b55ba7ff122ae74 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Sun, 31 May 2020 17:18:07 +0300 Subject: [PATCH] minor fixes --- .../12-nullish-coalescing-operator/article.md | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/1-js/02-first-steps/12-nullish-coalescing-operator/article.md b/1-js/02-first-steps/12-nullish-coalescing-operator/article.md index 7392b81f..ee06d5cb 100644 --- a/1-js/02-first-steps/12-nullish-coalescing-operator/article.md +++ b/1-js/02-first-steps/12-nullish-coalescing-operator/article.md @@ -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 ```