Оператор null-злиття (??)

Оператор null-злиття (??) – логічний оператор, що повертає свій правий операнд, коли його лівий операнд – null чи undefined, інакше – повертає лівий оператор.

Спробуйте його в дії

Синтаксис

leftExpr ?? rightExpr

Опис

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

Оператор null-злиття має п'ятий з кінця пріоритет оператора – зразу після || і зразу перед умовним (тернарним) оператором.

Як оператор логічного І (&&), так і оператор логічного АБО (||) не можна безпосередньо поєднувати з ??. Така спроба призведе до викидання синтаксичної помилки.

null || undefined ?? "foo"; // запускає SyntaxError
true && undefined ?? "foo"; // запускає SyntaxError

Натомість слід додати дужки, для явного задання пріоритету:

(null || undefined) ?? "foo"; // повертає "foo"

Приклади

Застосування оператора null-злиття

В цьому прикладі надаються усталені значення, однак значення, відмінні від null чи undefined, зберігаються.

const nullValue = null;
const emptyText = ""; // хибність
const someNumber = 42;

const valA = nullValue ?? "усталене для A";
const valB = emptyText ?? "усталене для B";
const valC = someNumber ?? 0;

console.log(valA); // "усталене для A"
console.log(valB); // "" (оскільки порожній рядок не є null чи undefined)
console.log(valC); // 42

Присвоєння змінній усталеного значення

Раніше при потребі присвоїти змінній усталене значення загальноприйнятим патерном було використання логічного оператора АБО (||):

let foo;

// foo ніколи не було присвоєне будь-яке значення, тож в ній досі undefined
const someDummyText = foo || "Привіт!";

Проте у зв'язку з тим, що || – булів логічний оператор, його лівий операнд зводиться до булевого значення, і будь-яке значення хибності (0, '', NaN, null, false тощо) не повертається. Така логіка може призвести до неочікуваних наслідків, якщо 0, '' чи NaN вважаються дійсними значеннями.

const count = 0;
const text = "";

const qty = count || 42;
const message = text || "агов!";
console.log(qty); // 42, а не 0
console.log(message); // "агов!", а не ""

Оператор null-злиття уникає цієї пастки, повертаючи другий операнд, коли перший зводиться або до null, або до undefined (але не до інших значень хибності):

const myText = ""; // Порожній рядок (що також є значенням хибності)

const notFalsyText = myText || "Привіт, світе";
console.log(notFalsyText); // Привіт, світе

const preservingFalsy = myText ?? "Привіт, сусіди";
console.log(preservingFalsy); // '' (оскільки myText не є ані undefined, ані null)

Закорочення

Подібно до логічних операторів АБО та І, вираз справа не обчислюється, якщо вираз зліва не є ані null, ані undefined.

function a() {
  console.log("a була викликана");
  return undefined;
}
function b() {
  console.log("b була викликана");
  return false;
}
function c() {
  console.log("c була викликана");
  return "foo";
}

console.log(a() ?? c());
// Виводить "a була викликана", потім "c була викликана", і потім – "foo"
// оскільки a() повертає undefined, тож обчислюються обидва вирази

console.log(b() ?? c());
// Виводить "b була викликана", потім "false"
// оскільки b() повернув false (а не null чи undefined), то вираз
// справа не був обчислений

Взаємини з оператором необов'язкового ланцюжка (?.)

Оператор null-злиття обробляє undefined і null як особливі значення, так само як оператор необов'язкового ланцюжка (?.), котрий є корисним для доступу до властивості об'єкта, котрий може виявитись null чи undefined. Поєднуючи їх, можна безпечно звертатися до властивості об'єкта, котрий може виявитись відсутнім, і задати усталене значення на такий випадок.

const foo = { someFooProp: "привіт" };

console.log(foo.someFooProp?.toUpperCase() ?? "недоступно"); // "ПРИВІТ"
console.log(foo.someBarProp?.toUpperCase() ?? "недоступно"); // "недоступно"

Специфікації

Сумісність із браузерами

desktop mobile server
Chrome Edge Firefox Internet Explorer Opera Safari WebView Android Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet Deno Node.js
Nullish coalescing operator (??)
Chrome Full support 80
Edge Full support 80
Firefox Full support 72
Internet Explorer No support No
Opera Full support 67
Safari Full support 13.1
WebView Android Full support 80
Chrome Android Full support 80
Firefox for Android Full support 79
Opera Android Full support 57
Safari on iOS Full support 13.4
Samsung Internet Full support 13.0
Deno Full support 1.0
Node.js Full support 14.0.0

Дивіться також