Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Оператор optional chaining». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Optional chaining (`?.`), це оператор із ES2020, який дозволяє безпечно звертатися до властивостей, методів та елементів, навіть якщо частина ланцюжка дорівнює `null` або `undefined`.** Якщо значення перед `?.` існує, повертається властивість; якщо воно `null` чи `undefined`, увесь вираз повертає `undefined` і код не падає з `TypeError`. Працює в трьох формах: `obj?.prop`, `obj.method?.()` та `arr?.[0]`. Часто йде в парі з `??`, який підставляє значення за замовчуванням. ```javascript const user = { profile: { name: 'Alice' } }; console.log(user.address?.city); // undefined, без помилки console.log(user.address?.city ?? '-'); // "-" ``` **Ключове:** `obj?.prop` це скорочення від `obj == null ? undefined : obj.prop`, тобто перевірка на `null` і `undefined` вбудована в сам доступ до властивості.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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`, а не від відсутнього методу. - **Використовувати `?.` зліва від присвоєння.** Це синтаксична помилка, оператор працює тільки на читання.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.