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 ba13cc7be..c4d01d415 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 @@ -2,15 +2,19 @@ [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 не є абсолютно новим. Це просто хороший синтаксис, щоб отримати перше "визначене" значення з двох. @@ -20,11 +24,9 @@ result = (a !== null && a !== undefined) ? a : b; ``` -Тепер повинно бути абсолютно зрозуміло, що робить `??`. Подивімось, де це допомагає. - - -Наприклад, тут ми показуємо значення у змінній `user`, якщо її значення не `null/undefined`, інакше -- показуємо `Анонімний`: +Тепер повинно бути абсолютно зрозуміло, що робить `??`. Розгляньмо де це допомагає. +Наприклад, тут ми показуємо значення у змінній `user`, якщо її значення не `null`/`undefined`, інакше -- показуємо `Анонімний`: Ось приклад з `user`, якому не присвоєне ім’я: @@ -34,11 +36,11 @@ let user; alert(user ?? "Анонімний"); // Анонімний (user є undefined) ``` -Ми також можемо використовувати послідовність з `??`, щоб вибрати перше значення зі списку, яке не є `null/undefined`. +Ми також можемо використовувати послідовність з `??`, щоб вибрати перше значення зі списку, яке не є `null`/`undefined`. Скажімо, у нас є дані користувача в змінних `firstName`, `lastName` або `nickName`. Всі вони можуть бути не визначені, якщо користувач вирішив не вводити значення. -Ми хотіли б показати ім’я користувача, використовуючи одну з цих змінних, або показати "Анонімний", якщо всі вони `null/undefined`. +Ми хотіли б показати ім’я користувача, використовуючи одну з цих змінних, або показати `"Анонімний"`, якщо всі вони `null`/`undefined`. Використаймо оператор `??` для цього: @@ -70,19 +72,20 @@ alert(firstName || lastName || nickName || "Анонімний"); // Супер */!* ``` -Історично, оператор АБО `||` був першим. Він існує з початку JavaScript, тому розробники використовували його для цих цілей протягом тривалого часу. +Раніше був доступним лише оператор АБО `||`. Протягом тривалого часу розробники використовували для цих цілей саме його, бо він був єдиним з доступних варіантів. -З іншого боку, оператор об’єднання з null `??` було нещодавно додано в JavaScript, і причиною того було те, що люди були не дуже задоволені `||`. +Але нещодавно в JavaScript було додано оператор об’єднання з null `??`, і причиною цього було те, що люди були не до кінця задоволені `||`. Важлива різниця між ними полягає в тому, що: -- `||` повертає перше *істинне* значення. -- `??` повертає перше *визначене* значення. -Інакше кажучи, оператор `||` не розрізняє, чи значення `false`, `0`, порожній рядок `""` чи `null/undefined`. Всі вони однакові -- хибні значення. Якщо будь-яке з них є першим аргументом `||`, тоді ми отримаємо другий аргумент як результат. +- `||` повертає перше _істинне_ значення. +- `??` повертає перше _визначене_ значення. + +Інакше кажучи, оператор `||` опрацьовує значення `false`, `0` і порожній рядок `""` так само, як `null`/`undefined`. Бо вони всі є хибними значеннями (при перетворенні на булевий тип стають `false`). Оператор `||` поверне як результат другий аргумент не лише якщо значення є `null`/`undefined`. А і якщо значення є `false`, `0` чи порожнім рядком `""`. -Однак на практиці, ми хочемо використовувати типове значення лише тоді, коли змінна `null/undefined`. Тобто, коли значення дійсно невідоме/не встановлене. +Однак на практиці дуже часто ми хочемо використовувати типове значення (другий аргумент) лише тоді, коли значення змінної є саме `null`/`undefined`. Тобто, коли значення дійсно невідоме/не встановлене. -Наприклад, розгляньте це: +До прикладу: ```js run let height = 0; @@ -91,18 +94,18 @@ 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 let height = null; @@ -114,7 +117,7 @@ let area = (height ?? 100) * (width ?? 50); alert(area); // 5000 ``` -В іншому випадку, якщо ми опускаємо дужки, то, оскільки `*` має вищий пріоритет, ніж `??`, то він буде виконуватися першим, що призводить до неправильних результатів. +В іншому випадку, якщо ми опускаємо дужки, то, оскільки `*` має вищий пріоритет, ніж `??`, то `*` буде виконуватися першим, що призводить до неправильних результатів. ```js // без дужок @@ -131,7 +134,7 @@ let area = height ?? (100 * width) ?? 50; Код нижче викликає синтаксичну помилку: ```js run -let x = 1 && 2 ?? 3; // Синтаксична помилка +let x = 1 && 2 ?? 3; // Виконання коду зупиниться і в консолі з'явиться повідомлення про синтаксичну помилку ``` Обмеження є досить спірним, воно було додано до специфікації мови з метою уникнення помилок програмування, коли люди почнуть переходити з `||` до `??`. @@ -150,12 +153,12 @@ alert(x); // 2 - Оператор об’єднання з null `??` надає короткий спосіб вибору першого "визначеного" значення зі списку. - Він використовується для присвоєння типових значень до змінних: + Він використовується для присвоєння типових значень до змінних: ```js // встановлює height=100, якщо height null чи undefined height = height ?? 100; ``` -- Оператор `??` має дуже низький пріоритет -- трохи вищий, ніж `?` та `=`, тому розглядайте додавання дужок при використанні його у виразах. +- Оператор `??` має дуже низький пріоритет -- трохи вищий, ніж `?` та `=`, тому додавайте дужки при використанні його у виразах. - Цей оператор заборонено використовувати з `||` або `&&` без явних дужок.