Оператор null-об'єднання

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

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

Синтаксис

лівийВираз ?? правийВираз

Опис

Оператор null-об'єднання повертає результати свого правого виразу, якщо лівий вираз дорівнює або null, або undefined.

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

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

let foo;
...
// змінній foo ще не присвоювали значення, тому вона ще дорівнює undefined
let someDummyText = foo || 'Привіт!';

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

let count;
let text;
...
count = 0;
text = "";
...
let qty = count || 42;
let message = text || "привіт!";
console.log(qty);     // 42, а не 0
console.log(message); // "привіт!", а не ""

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

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

let notFalsyText = myText || 'Привіт';
console.log(notFalsyText); // Привіт

let 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), правий
// вираз не обчислювався

Не утворює ланцюгів з операторами І чи АБО

Неможливо об'єднати оператори І (&&) та АБО (||) безпосередньо з ??. В таких випадках буде викинуто помилку SyntaxError.

null || undefined ?? "foo"; // викидає SyntaxError
true || undefined ?? "foo"; // викидає SyntaxError

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

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

Зв'язок з оператором необов'язкового ланцюгування (?.)

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

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

console.log(foo.someFooProp?.toUpperCase());  // "ПРИВІТ"
console.log(foo.someBarProp?.toUpperCase()); // undefined

Приклади

У цьому прикладі ми задаємо початкові значення, але залишаємо значення, які не дорівнюють null чи undefined.

function getMiscObj(){
  return {
    aNullProperty: null,
    emptyText: "",
    someNumber: 42
  };
};

const miscObj = getMiscObj();

const newObj = {};
newObj.propA = miscObj.aNullProperty ?? "початкове для A";
newObj.propB = miscObj.emptyText ?? "початкове для B";
newObj.propC = miscObj.someNumber ?? 0;

console.log(newObj.propA); // "початкове для A"
console.log(newObj.propB); // "" (оскільки порожній рядок не дорівнює null чи undefined)
console.log(newObj.propC); // 42

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

Специфікація Статус Коментар
Proposal for the "nullish coalescing" operator Стадія 3

Сумісність з веб-переглядачами

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Nullish coalescing operator (??)
Experimental
Chrome No support NoEdge No support NoFirefox No support NoIE No support NoOpera No support NoSafari No support NoWebView Android No support NoChrome Android No support NoFirefox Android No support NoOpera Android No support NoSafari iOS No support NoSamsung Internet Android No support Nonodejs No support No

Legend

No support  
No support
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.

Заувага: Відповідний PR вже був злитий, і дані скоро мають з'явитись на сторінці.

Хід реалізації

Наведена нижче таблиця надає щоденний статус реалізації цієї функціональності, оскільки функціональність ще не досягла кросбраузерної стабільності. Дані генеруються запуском відповідних тестів функціональності у Test262, стандартному тестовому наборі JavaScript, на нічній збірці чи на останньому релізі рушія JavaScript кожного веб-переглядача.

Див. також