[recent browser="new"]
Оператор об’єднання з null (англійською nullish coalescing operator) записується як два знаки питання ??
.
Для зручності формулювання, далі в цій главі під виразом "визначене значення" ми будемо мати на увазі, що значення не є `null` і не є `undefined`.
Вираз "визначене значення" не є загальновизнаним терміном. Це придуманий нами вираз, який ми використовуємо в цій главі для зручності.
Вираз a ?? b
поверне:
a
, якщоa
визначене,b
, якщоa
не визначене.
Інакше кажучи, ??
повертає перший аргумент, якщо він не null
/undefined
. Або, якщо перший аргумент є null
або undefined
, то повертає другий аргумент.
Оператор об’єднання з null не є абсолютно новим. Це просто хороший синтаксис, щоб отримати перше "визначене" значення з двох.
Ми можемо переписати вираз result = a ?? b
, використовуючи оператори, які ми вже знаємо:
result = a !== null && a !== undefined ? a : b;
Тепер повинно бути абсолютно зрозуміло, що робить ??
. Розгляньмо де це допомагає.
Наприклад, тут ми показуємо значення у змінній user
, якщо її значення не null
/undefined
, інакше -- показуємо Анонімний
:
Ось приклад з user
, якому не присвоєне ім’я:
let user;
alert(user ?? "Анонімний"); // Анонімний (user є undefined)
Ми також можемо використовувати послідовність з ??
, щоб вибрати перше значення зі списку, яке не є null
/undefined
.
Скажімо, у нас є дані користувача в змінних firstName
, lastName
або nickName
. Всі вони можуть бути не визначені, якщо користувач вирішив не вводити значення.
Ми хотіли б показати ім’я користувача, використовуючи одну з цих змінних, або показати "Анонімний"
, якщо всі вони null
/undefined
.
Використаймо оператор ??
для цього:
let firstName = null;
let lastName = null;
let nickName = "Суперкодер";
// показує перше визначене значення:
*!*
alert(firstName ?? lastName ?? nickName ?? "Анонімний"); // Суперкодер
*/!*
Оператор АБО ||
може бути використаний таким же чином, як ??
, як це було описано в попередній главі.
Наприклад, у коді вище, ми могли б замінити ??
на ||
і все ще отримали б той самий результат:
let firstName = null;
let lastName = null;
let nickName = "Суперкодер";
// показує перше істинне значення:
*!*
alert(firstName || lastName || nickName || "Анонімний"); // Суперкодер
*/!*
Раніше був доступним лише оператор АБО ||
. Протягом тривалого часу розробники використовували для цих цілей саме його, бо він був єдиним з доступних варіантів.
Але нещодавно в JavaScript було додано оператор об’єднання з null ??
, і причиною цього було те, що люди були не до кінця задоволені ||
.
Важлива різниця між ними полягає в тому, що:
||
повертає перше істинне значення.??
повертає перше визначене значення.
Інакше кажучи, оператор ||
опрацьовує значення false
, 0
і порожній рядок ""
так само, як null
/undefined
. Бо вони всі є хибними значеннями (при перетворенні на булевий тип стають false
). Оператор ||
поверне як результат другий аргумент не лише якщо значення є null
/undefined
. А і якщо значення є false
, 0
чи порожнім рядком ""
.
Однак на практиці дуже часто ми хочемо використовувати типове значення (другий аргумент) лише тоді, коли значення змінної є саме null
/undefined
. Тобто, коли значення дійсно невідоме/не встановлене.
До прикладу:
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
height || 100
перетворює значення змінноїheight
в булеве значення, і тоді якщо воноfalse
, то повертає другий аргумент. А0
після перетворення в булеве значення теж будеfalse
.- тут результатом
||
є другий аргумент,100
. Навіть тоді, коли значення0
нас влаштовує.
- тут результатом
height ?? 100
перевіряє чи значення змінноїheight
не єnull
/undefined
.- оператор
??
повертає нам значення змінноїheight
, тобто0
.
- оператор
На практиці нульова висота часто є дійсним значенням, яке не слід замінювати на типове значення. Отже, навідміну від ||
, ??
в цій ситуації робить саме те, що нам треба.
Пріоритет оператора ??
такий самий, як у ||
. Він дорівнює 3
у таблиці MDN.
Це означає, що, як і ||
, оператор об’єднання з null ??
виконується раніше за =
та ?
, але після більшості інших операцій, таких як +
, *
.
let height = null;
let width = null;
// важливо: використовуйте дужки
let area = (height ?? 100) * (width ?? 50);
alert(area); // 5000
В іншому випадку, якщо ми опускаємо дужки, то, оскільки *
має вищий пріоритет, ніж ??
, то *
буде виконуватися першим, що призводить до неправильних результатів.
// без дужок
let area = height ?? 100 * width ?? 50;
// ...працює так само, як попередній вираз (мабуть, це не те, що ми хочемо):
let area = height ?? 100 * width ?? 50;
З міркувань безпеки, JavaScript забороняє використання ??
разом з операторами &&
та ||
, якщо пріоритет явно не вказаний дужками.
Код нижче викликає синтаксичну помилку:
let x = 1 && 2 ?? 3; // Виконання коду зупиниться і в консолі з'явиться повідомлення про синтаксичну помилку
Обмеження є досить спірним, воно було додано до специфікації мови з метою уникнення помилок програмування, коли люди почнуть переходити з ||
до ??
.
Використовуйте явні дужки, щоб працювати з цим оператором:
*!*
let x = (1 && 2) ?? 3; // Працює
*/!*
alert(x); // 2
-
Оператор об’єднання з null
??
надає короткий спосіб вибору першого "визначеного" значення зі списку.Він використовується для присвоєння типових значень до змінних:
// встановлює height=100, якщо height null чи undefined height = height ?? 100;
-
Оператор
??
має дуже низький пріоритет -- трохи вищий, ніж?
та=
, тому додавайте дужки при використанні його у виразах. -
Цей оператор заборонено використовувати з
||
або&&
без явних дужок.