Skip to content

Fix while for #684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 37 additions & 34 deletions 1-js/02-first-steps/12-nullish-coalescing-operator/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,31 @@

[recent browser="new"]

Оператор об’єднання з null записується як два знаки питання `??`.
Оператор об’єднання з null (англійською nullish coalescing operator) записується як два знаки питання `??`.

Оскільки `null` і `undefined` сприймаються однаково, ми введемо спеціальну домовленість. В цій статті ми будемо вважати, що значення виразу "визначене", якщо воно відрізняється від `null` та `undefined`.
```smart header="Зверніть увагу!"
Для зручності формулювання, далі в цій главі під виразом "визначене значення" ми будемо мати на увазі, що значення не є `null` і не є `undefined`.
Вираз "визначене значення" не є загальновизнаним терміном. Це придуманий нами вираз, який ми використовуємо в цій главі для зручності.
```

Вираз `a ?? b` поверне:

Результатом `a ?? b` буде:
- `a`, якщо `a` визначене,
- `b`, якщо `a` не визначене.

Інакше кажучи, `??` повертає перший аргумент, якщо він не `null/undefined`. Інакше, другий.
Інакше кажучи, `??` повертає перший аргумент, якщо він не `null`/`undefined`. Або, якщо перший аргумент є `null` або `undefined`, то повертає другий аргумент.

Оператор об’єднання з null не є абсолютно новим. Це просто хороший синтаксис, щоб отримати перше "визначене" значення з двох.

Ми можемо переписати вираз `result = a ?? b`, використовуючи оператори, які ми вже знаємо:

```js
result = (a !== null && a !== undefined) ? a : b;
result = a !== null && a !== undefined ? a : b;
```

Тепер повинно бути абсолютно зрозуміло, що робить `??`. Подивімось, де це допомагає.


Наприклад, тут ми показуємо значення у змінній `user`, якщо її значення не `null/undefined`, інакше -- показуємо `Анонімний`:
Тепер повинно бути абсолютно зрозуміло, що робить `??`. Розгляньмо де це допомагає.

Наприклад, тут ми показуємо значення у змінній `user`, якщо її значення не `null`/`undefined`, інакше -- показуємо `Анонімний`:

Ось приклад з `user`, якому не присвоєне ім’я:

Expand All @@ -34,11 +36,11 @@ let user;
alert(user ?? "Анонімний"); // Анонімний (user є undefined)
```

Ми також можемо використовувати послідовність з `??`, щоб вибрати перше значення зі списку, яке не є `null/undefined`.
Ми також можемо використовувати послідовність з `??`, щоб вибрати перше значення зі списку, яке не є `null`/`undefined`.

Скажімо, у нас є дані користувача в змінних `firstName`, `lastName` або `nickName`. Всі вони можуть бути не визначені, якщо користувач вирішив не вводити значення.

Ми хотіли б показати ім’я користувача, використовуючи одну з цих змінних, або показати "Анонімний", якщо всі вони `null/undefined`.
Ми хотіли б показати ім’я користувача, використовуючи одну з цих змінних, або показати `"Анонімний"`, якщо всі вони `null`/`undefined`.

Використаймо оператор `??` для цього:

Expand Down Expand Up @@ -70,19 +72,20 @@ alert(firstName || lastName || nickName || "Анонімний"); // Супер
*/!*
```

Історично, оператор АБО `||` був першим. Він існує з початку JavaScript, тому розробники використовували його для цих цілей протягом тривалого часу.
Раніше був доступним лише оператор АБО `||`. Протягом тривалого часу розробники використовували для цих цілей саме його, бо він був єдиним з доступних варіантів.

З іншого боку, оператор об’єднання з null `??` було нещодавно додано в JavaScript, і причиною того було те, що люди були не дуже задоволені `||`.
Але нещодавно в JavaScript було додано оператор об’єднання з null `??`, і причиною цього було те, що люди були не до кінця задоволені `||`.

Важлива різниця між ними полягає в тому, що:
- `||` повертає перше *істинне* значення.
- `??` повертає перше *визначене* значення.

Інакше кажучи, оператор `||` не розрізняє, чи значення `false`, `0`, порожній рядок `""` чи `null/undefined`. Всі вони однакові -- хибні значення. Якщо будь-яке з них є першим аргументом `||`, тоді ми отримаємо другий аргумент як результат.
- `||` повертає перше _істинне_ значення.
- `??` повертає перше _визначене_ значення.

Однак на практиці, ми хочемо використовувати типове значення лише тоді, коли змінна `null/undefined`. Тобто, коли значення дійсно невідоме/не встановлене.
Інакше кажучи, оператор `||` опрацьовує значення `false`, `0` і порожній рядок `""` так само, як `null`/`undefined`. Бо вони всі є хибними значеннями (при перетворенні на булевий тип стають `false`). Оператор `||` поверне як результат другий аргумент не лише якщо значення є `null`/`undefined`. А і якщо значення є `false`, `0` чи порожнім рядком `""`.

Наприклад, розгляньте це:
Однак на практиці дуже часто ми хочемо використовувати типове значення (другий аргумент) лише тоді, коли значення змінної є саме `null`/`undefined`. Тобто, коли значення дійсно невідоме/не встановлене.

До прикладу:

```js run
let height = 0;
Expand All @@ -91,20 +94,20 @@ alert(height || 100); // 100
alert(height ?? 100); // 0
```

- `height || 100` перевіряє чи має змінна `height` має хибне значення, і `0` -- це дійсно хибне значення.
- отже, результатом `||` є другий аргумент, `100`.
- `height ?? 100` перевіряє змінну `height`, чи вона `null/undefined`, і це не так,
- отже, результат -- `height` "як є", тобто `0`.
- `height || 100` перетворює значення змінної `height` в булеве значення, і тоді якщо воно `false`, то повертає другий аргумент. А `0` після перетворення в булеве значення теж буде `false`.
- тут результатом `||` є другий аргумент, `100`. Навіть тоді, коли значення `0` нас влаштовує.
- `height ?? 100` перевіряє чи значення змінної `height` не є `null`/`undefined`.
- оператор `??` повертає нам значення змінної `height`, тобто `0`.

На практиці нульова висота часто є дійсним значенням, яке не слід замінювати на типове значення. Отже, `??` робить саме те, що треба.
На практиці нульова висота часто є дійсним значенням, яке не слід замінювати на типове значення. Отже, навідміну від `||`, `??` в цій ситуації робить саме те, що нам треба.

## Пріоритет

Пріоритет оператора `??` такий самий, як у `||`. Він дорівнює `3` у [таблиці MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table).

Це означає, що, як і `||`, оператор об’єднання з null `??` оцінюється до `=` та `?`, але після більшості інших операцій, таких як `+`, `*`.
Це означає, що, як і `||`, оператор об’єднання з null `??` виконується раніше за `=` та `?`, але після більшості інших операцій, таких як `+`, `*`.

``` js
```js
let height = null;
let width = null;

Expand All @@ -114,14 +117,14 @@ let area = (height ?? 100) * (width ?? 50);
alert(area); // 5000
```

В іншому випадку, якщо ми опускаємо дужки, то, оскільки `*` має вищий пріоритет, ніж `??`, то він буде виконуватися першим, що призводить до неправильних результатів.
В іншому випадку, якщо ми опускаємо дужки, то, оскільки `*` має вищий пріоритет, ніж `??`, то `*` буде виконуватися першим, що призводить до неправильних результатів.

```js
// без дужок
let area = height ?? 100 * width ?? 50;

// ...працює так само, як попередній вираз (мабуть, це не те, що ми хочемо):
let area = height ?? (100 * width) ?? 50;
let area = height ?? 100 * width ?? 50;
```

### Використання ?? разом з && або ||
Expand All @@ -131,7 +134,7 @@ let area = height ?? (100 * width) ?? 50;
Код нижче викликає синтаксичну помилку:

```js run
let x = 1 && 2 ?? 3; // Синтаксична помилка
let x = 1 && 2 ?? 3; // Виконання коду зупиниться і в консолі з'явиться повідомлення про синтаксичну помилку
```

Обмеження є досить спірним, воно було додано до специфікації мови з метою уникнення помилок програмування, коли люди почнуть переходити з `||` до `??`.
Expand All @@ -150,12 +153,12 @@ alert(x); // 2

- Оператор об’єднання з null `??` надає короткий спосіб вибору першого "визначеного" значення зі списку.

Він використовується для присвоєння типових значень до змінних:
Він використовується для присвоєння типових значень до змінних:

```js
// встановлює height=100, якщо height null чи undefined
height = height ?? 100;
```
```js
// встановлює height=100, якщо height null чи undefined
height = height ?? 100;
```

- Оператор `??` має дуже низький пріоритет -- трохи вищий, ніж `?` та `=`, тому розглядайте додавання дужок при використанні його у виразах.
- Оператор `??` має дуже низький пріоритет -- трохи вищий, ніж `?` та `=`, тому додавайте дужки при використанні його у виразах.
- Цей оператор заборонено використовувати з `||` або `&&` без явних дужок.
Loading