Skip to main content

Звернення до неіснуючої властивості об'єкта

Якщо звернутися до неіснуючої властивості об'єкта, помилки не буде, а результатом стане undefined. Помилка виникає лише тоді, коли це undefined намагаються використати як об'єкт і прочитати вже його властивість.

Теорія

TL;DR

  • obj.missing повертає undefined, а не кидає виняток.
  • Так само поводиться динамічний доступ obj[key].
  • TypeError з'являється на наступному кроці ланцюжка: undefined.city.
  • Безпечні способи: ручна перевірка через &&, optional chaining ?., значення за замовчуванням через ??.
  • Щоб відрізнити «властивості немає» від «властивість дорівнює undefined», потрібні in або hasOwnProperty.

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

javascript
const user = { name: 'Maria' }; console.log(user.name); // "Maria" console.log(user.age); // undefined console.log(user.address); // undefined

JavaScript не кидає помилку, він просто повертає undefined.

Чому повертається саме undefined

Під час читання властивості рушій робить таке:

  1. Перевіряє, чи є властивість у самому об'єкті.
  2. Якщо є, повертає її значення.
  3. Якщо немає, шукає далі по ланцюжку прототипів.
  4. Якщо не знайшов ніде, повертає undefined.
javascript
user.hasOwnProperty('age'); // false user.age; // undefined

Це свідоме рішення мови: відсутня властивість, це не помилкова ситуація, а звичайний стан даних.

Коли все-таки буде помилка

Помилка з'явиться, якщо звернутися далі по ланцюжку:

javascript
console.log(user.address.city); // TypeError

Причина: user.address, це undefined, а в undefined не можна запитувати властивості. Текст помилки в браузері виглядає приблизно так: TypeError: Cannot read properties of undefined (reading 'city').

Те саме стосується null: обидва ці значення не мають обгортки-об'єкта, тому будь-яке читання властивості на них падає.

Як безпечно читати вкладені властивості

Спосіб 1. Ручна перевірка.

javascript
if (user.address && user.address.city) { console.log(user.address.city); }

Спосіб 2. Optional chaining ?. (сучасний підхід).

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

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

Спосіб 3. Значення за замовчуванням через ??.

javascript
console.log(user.address?.city ?? 'Не вказано'); // "Не вказано"

Динамічний доступ і перевірка наявності

Через квадратні дужки поведінка та сама:

javascript
const key = 'email'; console.log(user[key]); // undefined, якщо властивості немає

Проблема в тому, що undefined повертається і тоді, коли властивість існує, але її значення дорівнює undefined. Щоб відрізнити ці два випадки, потрібні окремі перевірки:

javascript
const account = { email: undefined }; account.email; // undefined 'email' in account; // true, властивість є account.hasOwnProperty('email'); // true, і вона власна Object.hasOwn(account, 'email'); // true, сучасний варіант

in враховує і властивості з прототипу, а hasOwnProperty та Object.hasOwn лише власні.

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

СитуаціяРезультатПояснення
user.ageundefinedвластивості немає
user.age.cityTypeErrorundefined не є об'єктом
'age' in userfalseперевірка наявності властивості
user.hasOwnProperty('age')falseперевірка лише власних властивостей
user.name ?? 'немає''Maria'повертається значення
user.age ?? 'немає''немає'підставляється значення за замовчуванням
ПоведінкаЩо відбувається
------
obj.missingповертає undefined
Помилки немаєнавіть якщо властивості не існує
Помилка з'являєтьсяпід час спроби піти глибше (undefined.city)
Рішеннявикористати ?. або ??

Приклад для закріплення:

javascript
const user = { name: 'Maria' }; console.log(user.age); // undefined console.log(user.age?.value); // undefined (без помилки) console.log(user.age ?? 'немає'); // "немає" console.log(user.age.value); // TypeError

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

  • Розраховують на помилку там, де її немає. Одруківка в назві властивості тихо дає undefined, і баг спливає значно пізніше, уже в іншому місці коду.
  • Читають глибокий ланцюжок без ?.. Дані з API часто приходять неповними, і data.user.profile.avatar падає на першому ж відсутньому рівні.
  • Ставлять ?. лише в кінці ланцюжка. user.address?.city не рятує, якщо undefined може бути сам user. Тоді потрібно user?.address?.city.
  • Плутають «немає властивості» і «значення undefined». Порівняння obj.key === undefined не розрізняє ці випадки, для цього є in та Object.hasOwn.
  • Викликають неіснуючий метод. obj.doSomething() кидає TypeError: obj.doSomething is not a function, бо викликати undefined не можна. Безпечна форма, це obj.doSomething?.().

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

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

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