Skip to main content

Відсутня властивість чи значення undefined

Щоб відрізнити властивість зі значенням undefined від властивості, якої в об'єкті немає, перевіряють наявність ключа оператором in або Object.hasOwn(), а не порівнюють значення з undefined. Це дві різні ситуації, які дають однакове значення при читанні, тому одного порівняння недостатньо.

Теорія

TL;DR

  • obj.key === undefined перевіряє лише значення і повертає true і для наявного ключа зі значенням undefined, і для ключа, якого немає.
  • 'key' in obj перевіряє наявність ключа, разом з успадкованими від прототипу властивостями.
  • Object.hasOwn(obj, 'key') робить те саме для власних властивостей і є безпечнішим сучасним варіантом.
  • Точна перевірка «властивість є, але дорівнює undefined»: 'key' in obj && obj.key === undefined.
  • Читання відсутнього ключа не кидає помилку, воно просто повертає undefined, тому мовчазні баги тут дуже типові.

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

javascript
const obj = { a: undefined }; const obj2 = {}; // Значення однакове в обох випадках. console.log(obj.a); // undefined console.log(obj2.a); // undefined // А ключі різні. console.log('a' in obj); // true console.log('a' in obj2); // false

Перевірка наявності властивості

Спочатку згадаймо, як перевірити, чи є ключ в об'єкті:

javascript
'key' in obj // true, якщо властивість є (навіть якщо undefined) Object.hasOwn(obj, 'key') // те саме, тільки безпечніше і лише про власні властивості

Оператор 'key' in obj не говорить, чому дорівнює властивість, він лише перевіряє, що ключ існує в об'єкті. Різниця між ними в прототипі: in бачить і успадковані властивості, а Object.hasOwn() тільки ті, що лежать у самому об'єкті.

Властивість є, але дорівнює undefined

Ось об'єкт, у якому ключ явно заданий і має значення undefined:

javascript
const obj = { a: undefined };

А ось об'єкт, у якому такого ключа немає зовсім:

javascript
const obj2 = {};

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

Різниця на практиці

javascript
console.log('a' in obj); // true (властивість є) console.log('a' in obj2); // false (властивості немає) console.log(obj.a === undefined); // true console.log(obj2.a === undefined); // true (обидва дають true)

Проблема в тому, що проста перевірка obj.a === undefined не відрізняє «відсутність властивості» від «властивість є, але undefined». Це помітно там, де ключ несе сенс сам по собі: часткове оновлення запису, де { nickname: undefined } означає «стерти значення», а {} означає «не чіпати поле».

Рішення: комбінувати перевірки

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

javascript
if ('a' in obj && obj.a === undefined) { console.log('Властивість є, але значення undefined'); }

Тут 'a' in obj перевіряє наявність ключа, а obj.a === undefined перевіряє значення. Якщо успадковані властивості вам не потрібні, замініть перший доданок на Object.hasOwn(obj, 'a').

Приклад: порівняння всіх випадків

javascript
const data = { a: undefined, b: 10 }; console.log('a' in data, data.a); // true, undefined console.log('b' in data, data.b); // true, 10 console.log('c' in data, data.c); // false, undefined

Тільки для c оператор in поверне false. Для a він дає true, тобто ключ є, навіть якщо його значення undefined.

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

ПеревіркаЩо робитьВідрізняє наявність ключа?
obj.key === undefinedперевіряє тільки значенняНі
'key' in objперевіряє, чи є ключТак
'key' in obj && obj.key === undefinedперевіряє обидві умовиТак
Object.hasOwn(obj, 'key')сучасний аналог in для власних властивостейТак

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

  • Вважати obj.key === undefined перевіркою наявності. Вона дає true і для відсутнього ключа, і для ключа зі значенням undefined, тобто відповідає на інше питання.
  • Писати if (obj.key) замість порівняння. Значення 0, '', null, NaN і false є falsy, тому наявна властивість буде сприйнята як відсутня.
  • Забувати, що in бачить прототип. 'toString' in {} повертає true, бо метод приходить з Object.prototype. Для даних, що прийшли ззовні, беріть Object.hasOwn().
  • Плутати undefined і null. null є явним значенням «порожньо», його ключ існує, і obj.key === undefined для нього поверне false.
  • Покладатися на JSON.stringify() для перевірки. Він викидає властивості зі значенням undefined, тому { a: undefined } і {} перетворюються на однаковий рядок {}.
  • Писати key in obj без лапок. Тоді перевіряється значення змінної key, а не буквальний ключ "key".

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

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

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