Перевірка наявності властивості в об'єкті
Наявність властивості в об'єкті перевіряють оператором in, методом hasOwnProperty(), функцією Object.hasOwn() або порівнянням значення з undefined. Ці способи не взаємозамінні: вони по-різному поводяться з прототипом і по-різному реагують на властивість, значення якої дорівнює undefined.
Теорія
TL;DR
'key' in obj, найуніверсальніший спосіб: повертаєtrueі для власних, і для успадкованих від прототипу властивостей.obj.hasOwnProperty('key')перевіряє тільки власні властивості та ігнорує прототип, це класика.Object.hasOwn(obj, 'key'), сучасний стандарт з ES2022: та сама семантика, що йhasOwnProperty, але надійніша.obj.key !== undefinedперевіряє значення, а не ключ, тому дає хибний результат, коли значенням єundefined.- Коротке правило: потрібні всі властивості, беріть
in; потрібні тільки власні, берітьObject.hasOwn.
Швидкий приклад
const user = { name: 'Maria', age: 25 };
console.log('age' in user); // true
console.log('city' in user); // false
console.log(user.hasOwnProperty('age')); // true
console.log(Object.hasOwn(user, 'city')); // falseОператор in, найуніверсальніший спосіб
const user = { name: 'Maria', age: 25 };
console.log('age' in user); // true
console.log('city' in user); // falseОператор перевіряє, чи є ключ в об'єкті, разом з властивостями, успадкованими від прототипу. Ліворуч від in стоїть рядок або Symbol, праворуч, сам об'єкт.
Приклад зі спадкуванням:
const person = { species: 'human' };
const user = Object.create(person);
user.name = 'Maria';
console.log('species' in user); // true (успадковано)Тут species немає безпосередньо в user, але воно є в його прототипі person, тому in повертає true. Саме тому 'toString' in {} теж дає true: метод приходить з Object.prototype.
Метод hasOwnProperty(), тільки власні властивості
const user = { name: 'Maria', age: 25 };
console.log(user.hasOwnProperty('age')); // true
console.log(user.hasOwnProperty('city')); // falseНа відміну від in, метод ігнорує прототип і перевіряє лише ті властивості, які реально задані в самому об'єкті.
Приклад різниці:
const person = { species: 'human' };
const user = Object.create(person);
user.name = 'Maria';
console.log('species' in user); // true
console.log(user.hasOwnProperty('species')); // falseObject.hasOwn(), сучасний аналог hasOwnProperty
ES2022 додав безпечніший і читабельніший спосіб:
const user = { name: 'Maria' };
console.log(Object.hasOwn(user, 'name')); // true
console.log(Object.hasOwn(user, 'city')); // falseПрацює так само, як hasOwnProperty, але не залежить від того, що відбувається всередині самого об'єкта. Два випадки, де hasOwnProperty ламається, а Object.hasOwn ні:
// 1. Об'єкт без прототипу: методу hasOwnProperty просто немає.
const dict = Object.create(null);
dict.token = 1;
// dict.hasOwnProperty('token'); // TypeError
console.log(Object.hasOwn(dict, 'token')); // true
// 2. Власна властивість з таким самим іменем перекриває метод.
const data = { hasOwnProperty: () => false, id: 7 };
console.log(data.hasOwnProperty('id')); // false, перевизначено
console.log(Object.hasOwn(data, 'id')); // trueПеревірка на undefined, найпростіша, але не завжди точна
const user = { name: 'Maria' };
if (user.age !== undefined) {
console.log('Властивість age є');
} else {
console.log('Властивості age немає');
}Мінус: якщо властивість є, але її значення дорівнює undefined, ви отримаєте хибне спрацювання.
const user = { age: undefined };
console.log(user.age !== undefined); // false, хоча ключ існуєТак само помилковою є скорочена перевірка if (user.age): вона відкине 0, '', null і false, які є цілком валідними значеннями.
Порівняння способів
| Спосіб | Що перевіряє | Враховує прототип | Надійність |
|---|---|---|---|
'key' in obj | наявність ключа | Так | Відмінний вибір |
obj.hasOwnProperty('key') | тільки власні властивості | Ні | Класика |
Object.hasOwn(obj, 'key') | тільки власні властивості | Ні | Сучасний стандарт |
obj.key !== undefined | значення не undefined | Ні | Може бути хибним |
Щоб перевірити, чи є властивість в об'єкті, використовуйте
'key' in obj, коли важливі всі властивості разом з успадкованими, абоObject.hasOwn(obj, 'key'), коли потрібні тільки власні.
Типові помилки
- Плутати наявність ключа і його значення.
obj.key !== undefinedповернеfalseдля властивості, яка існує зі значеннямundefined. Перевіряйте ключ черезinабоObject.hasOwn. - Скорочувати до
if (obj.key). Значення0,'',null,NaNіfalseє хибними (falsy), тому існуючі властивості будуть «загублені». - Забувати про прототип. Оператор
inбачитьtoString,constructorта інші успадковані властивості, тому для перевірки даних, що прийшли ззовні, берітьObject.hasOwn. - Викликати
hasOwnPropertyна об'єкті зObject.create(null). Такий об'єкт не має прототипу, тому методу в нього немає і виклик кинеTypeError. - Довіряти
hasOwnProperty, коли дані прийшли від користувача. Вхідний JSON може містити власний ключhasOwnPropertyі перекрити метод.Object.hasOwnабоObject.prototype.hasOwnProperty.call(obj, key)від цього захищені. - Писати
inз ім'ям змінної без лапок.key in objперевіряє значення змінноїkey, а'key' in obj, буквальний ключ"key". Це різні перевірки.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.