Оператор 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. - Чудово поєднується з
??для значення за замовчуванням. - Не можна ставити зліва від присвоєння.
Швидкий приклад
const user = {
profile: {
name: 'Alice'
}
};
console.log(user.profile?.name); // "Alice"
console.log(user.address?.city); // undefined (без помилки)Проблема без optional chaining
Припустімо, є вкладений об'єкт:
const user = {
profile: {
name: 'Alice'
}
};Якщо спробувати звернутися до неіснуючого поля:
console.log(user.address.city); // TypeError: Cannot read properties of undefinedПомилка виникає тому, що
user.addressдорівнюєundefined, а спроба звернутися доundefined.cityламає код.
Розв'язання, оператор ?.:
console.log(user.address?.city); // undefined (без помилки)Якщо значення до ?. існує, повертається властивість. Якщо воно undefined або null, повертається undefined і програма не падає.
Форми синтаксису
1. Доступ до властивостей
user?.profile?.name // "Alice"
user?.address?.city // undefined2. Доступ до методів
user.sayHi?.(); // викличе метод, якщо він існує3. Доступ до елементів масиву
const arr = null;
console.log(arr?.[0]); // undefined (без помилки)Приклад із даними з API
const response = {
user: { name: 'Alice', address: null }
};
console.log(response.user?.address?.city); // undefinedБез ?. довелося б писати довгі перевірки:
response && response.user && response.user.address && response.user.address.cityOptional chaining разом із nullish coalescing
Ці два оператори часто застосовують у парі:
const city = user.address?.city ?? 'Не вказано';
console.log(city); // "Не вказано"?.безпечно звертається до властивості.??задає значення за замовчуванням, якщо результатundefinedабоnull.
На відміну від ||, оператор ?? не підмінює коректні «хибні» значення: 0 ?? 10 дає 0, тоді як 0 || 10 дає 10.
Що робить під капотом
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 |
Де не можна застосовувати
// не можна зліва від присвоєння
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, а не від відсутнього методу. - Використовувати
?.зліва від присвоєння. Це синтаксична помилка, оператор працює тільки на читання.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.