Оператор null-об'єднання (??
) - це логічний оператор, який повертає свій правий операнд, якщо його лівий операнд дорівнює null
чи undefined
, інакше, він повертає свій лівий операнд.
На відміну від логічного АБО (||
), лівий операнд повертається, якщо це хибне значення, яке не дорівнює null
чи undefined
. Іншими словами, якщо ви використовуєте ||
для надання значення за замовчуванням іншій змінній foo
, ви можете зіткнутися з неочікуваною поведінкою, якщо використовуєте хибні значення (напр., ''
або 0
). Дивіться нижче більше прикладів.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
See PR #1482 regarding the addition of this example.
Синтаксис
лівийВираз ?? правийВираз
Опис
Оператор 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 |
Сумісність з веб-переглядачами
BCD tables only load in the browser
Хід реалізації
Наведена нижче таблиця надає щоденний статус реалізації цієї функціональності, оскільки функціональність ще не досягла кросбраузерної стабільності. Дані генеруються запуском відповідних тестів функціональності у Test262, стандартному тестовому наборі JavaScript, на нічній збірці чи на останньому релізі рушія JavaScript кожного веб-переглядача.