Skip to main content

Оператор optional chaining

Optional chaining (?.), це сучасний оператор (ES2020), який дозволяє безпечно звертатися до властивостей об'єктів, навіть якщо частина ланцюжка дорівнює undefined або null. Замість довгої низки перевірок ви пишете один символ і отримуєте undefined там, де раніше був TypeError.

Теорія

TL;DR

  • ?. перериває обчислення ланцюжка, щойно зліва трапляється null або undefined, і повертає undefined.
  • Три форми: доступ до властивості obj?.prop, виклик методу obj.method?.(), доступ за індексом arr?.[0].
  • Еквівалент під капотом: obj == null ? undefined : obj.prop.
  • Перевіряє тільки null і undefined, а не «порожні» значення 0, '', false.
  • Чудово поєднується з ?? для значення за замовчуванням.
  • Не можна ставити зліва від присвоєння.

Швидкий приклад

javascript
const user = { profile: { name: 'Alice' } }; console.log(user.profile?.name); // "Alice" console.log(user.address?.city); // undefined (без помилки)

Проблема без optional chaining

Припустімо, є вкладений об'єкт:

javascript
const user = { profile: { name: 'Alice' } };

Якщо спробувати звернутися до неіснуючого поля:

javascript
console.log(user.address.city); // TypeError: Cannot read properties of undefined

Помилка виникає тому, що user.address дорівнює undefined, а спроба звернутися до undefined.city ламає код.

Розв'язання, оператор ?.:

javascript
console.log(user.address?.city); // undefined (без помилки)

Якщо значення до ?. існує, повертається властивість. Якщо воно undefined або null, повертається undefined і програма не падає.

Форми синтаксису

1. Доступ до властивостей

javascript
user?.profile?.name // "Alice" user?.address?.city // undefined

2. Доступ до методів

javascript
user.sayHi?.(); // викличе метод, якщо він існує

3. Доступ до елементів масиву

javascript
const arr = null; console.log(arr?.[0]); // undefined (без помилки)

Приклад із даними з API

javascript
const response = { user: { name: 'Alice', address: null } }; console.log(response.user?.address?.city); // undefined

Без ?. довелося б писати довгі перевірки:

javascript
response && response.user && response.user.address && response.user.address.city

Optional chaining разом із nullish coalescing

Ці два оператори часто застосовують у парі:

javascript
const city = user.address?.city ?? 'Не вказано'; console.log(city); // "Не вказано"
  • ?. безпечно звертається до властивості.
  • ?? задає значення за замовчуванням, якщо результат undefined або null.

На відміну від ||, оператор ?? не підмінює коректні «хибні» значення: 0 ?? 10 дає 0, тоді як 0 || 10 дає 10.

Що робить під капотом

javascript
obj?.prop // еквівалентно: obj == null ? undefined : obj.prop

Нестрога рівність == null істинна і для null, і для undefined, тому один оператор покриває обидва випадки. Важлива деталь: обчислення ланцюжка при цьому коротко замикається, тобто в a?.b.c решта виразу навіть не виконується, якщо a дорівнює null.

Де можна застосовувати

СитуаціяПрикладРезультат
Властивість об'єктаuser?.name'Alice' або undefined
Вкладені об'єктиuser?.address?.cityбезпечно
Виклик методуuser.method?.()викликається, якщо метод є
Елемент масивуarr?.[0]перший елемент або undefined

Де не можна застосовувати

javascript
// не можна зліва від присвоєння user?.name = 'Alex'; // SyntaxError // не годиться як перевірка існування: дає undefined, а не false if (user?.missing) { /* ... */ }

Підсумкова таблиця

Що робитьЯк працює
Optional chaining (?.)Безпечно звертається до властивості, не кидаючи помилку
Повертаєundefined, якщо трапляється null або undefined
Використовуєтьсяпри доступі до вкладених властивостей, методів та елементів
Комбінуєтьсячасто з ?? для значень за замовчуванням

Типові помилки

  • Ставити ?. у кожній ланці «про всяк випадок». Це маскує справжні баги: якщо user за контрактом завжди існує, user?.profile лише сховає помилку в даних.
  • Плутати з перевіркою на «порожнє». ?. реагує лише на null та undefined; 0, '' і false проходять далі як звичайні значення.
  • Комбінувати ?? з || або && без дужок. a ?? b || c це SyntaxError, потрібні явні дужки.
  • Забувати, що після ?. ланцюжок усе ще може впасти. У user?.address.city захищено лише user; якщо address дорівнює undefined, буде TypeError.
  • Викликати метод як user?.sayHi() замість user.sayHi?.(). Перший варіант захищає лише від відсутнього user, а не від відсутнього методу.
  • Використовувати ?. зліва від присвоєння. Це синтаксична помилка, оператор працює тільки на читання.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.