Звернення до неіснуючої властивості об'єкта
Якщо звернутися до неіснуючої властивості об'єкта, помилки не буде, а результатом стане undefined. Помилка виникає лише тоді, коли це undefined намагаються використати як об'єкт і прочитати вже його властивість.
Теорія
TL;DR
obj.missingповертаєundefined, а не кидає виняток.- Так само поводиться динамічний доступ
obj[key]. TypeErrorз'являється на наступному кроці ланцюжка:undefined.city.- Безпечні способи: ручна перевірка через
&&, optional chaining?., значення за замовчуванням через??. - Щоб відрізнити «властивості немає» від «властивість дорівнює
undefined», потрібніinабоhasOwnProperty.
Швидкий приклад
const user = { name: 'Maria' };
console.log(user.name); // "Maria"
console.log(user.age); // undefined
console.log(user.address); // undefinedJavaScript не кидає помилку, він просто повертає undefined.
Чому повертається саме undefined
Під час читання властивості рушій робить таке:
- Перевіряє, чи є властивість у самому об'єкті.
- Якщо є, повертає її значення.
- Якщо немає, шукає далі по ланцюжку прототипів.
- Якщо не знайшов ніде, повертає
undefined.
user.hasOwnProperty('age'); // false
user.age; // undefinedЦе свідоме рішення мови: відсутня властивість, це не помилкова ситуація, а звичайний стан даних.
Коли все-таки буде помилка
Помилка з'явиться, якщо звернутися далі по ланцюжку:
console.log(user.address.city); // TypeErrorПричина: user.address, це undefined, а в undefined не можна запитувати властивості. Текст помилки в браузері виглядає приблизно так: TypeError: Cannot read properties of undefined (reading 'city').
Те саме стосується null: обидва ці значення не мають обгортки-об'єкта, тому будь-яке читання властивості на них падає.
Як безпечно читати вкладені властивості
Спосіб 1. Ручна перевірка.
if (user.address && user.address.city) {
console.log(user.address.city);
}Спосіб 2. Optional chaining ?. (сучасний підхід).
console.log(user.address?.city); // undefined, але без помилкиЯкщо ліворуч від ?. стоїть null або undefined, JavaScript зупиняє обчислення всього ланцюжка і повертає undefined.
Спосіб 3. Значення за замовчуванням через ??.
console.log(user.address?.city ?? 'Не вказано');
// "Не вказано"Динамічний доступ і перевірка наявності
Через квадратні дужки поведінка та сама:
const key = 'email';
console.log(user[key]); // undefined, якщо властивості немаєПроблема в тому, що undefined повертається і тоді, коли властивість існує, але її значення дорівнює undefined. Щоб відрізнити ці два випадки, потрібні окремі перевірки:
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.age | undefined | властивості немає |
user.age.city | TypeError | undefined не є об'єктом |
'age' in user | false | перевірка наявності властивості |
user.hasOwnProperty('age') | false | перевірка лише власних властивостей |
user.name ?? 'немає' | 'Maria' | повертається значення |
user.age ?? 'немає' | 'немає' | підставляється значення за замовчуванням |
| Поведінка | Що відбувається | |
| --- | --- | |
obj.missing | повертає undefined | |
| Помилки немає | навіть якщо властивості не існує | |
| Помилка з'являється | під час спроби піти глибше (undefined.city) | |
| Рішення | використати ?. або ?? |
Приклад для закріплення:
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?.().
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.