Коротка відповідь
junior`in` — це оператор, що перевіряє наявність ключа в об’єкті або його прототипі; `hasOwnProperty` — це метод, що перевіряє лише власні властивості об’єкта. Тобто `in` повертає true, якщо ключ існує в ланцюжку прототипів, а `hasOwnProperty` — лише коли ключ належить саме цьому об’єкту.
Повне пояснення
Що це і навіщо
inвикористовується, коли треба знати, чи існує певний ключ у об’єкті або в його прототипі. Це корисно для перевірки наявності властивостей, що успадковуються.hasOwnPropertyзастосовується, коли потрібно переконатися, що властивість належить саме даному об’єкту, а не його прототипу.
Ключові принципи/терміни
- Prototype chain – ланцюжок прототипів, через який JavaScript шукає властивості.
- Own property – власна властивість об’єкта, не успадкована.
Як це працює
- Оператор
inвиконує пошук ключа по всьому ланцюжку прототипів і повертаєtrue, якщо знайде. - Метод
hasOwnPropertyвикликається на конкретному об’єкті і повертаєtrue, лише якщо ключ є власною властивістю.
Практика і реалізація
const obj = {a: 1};
Object.prototype.b = 2;
console.log('b' in obj); // true – через prototype
console.log(obj.hasOwnProperty('b')); // false – не власна
Тестування
- У Jest можна перевірити:
expect('b' in obj).toBe(true);
expect(obj.hasOwnProperty('b')).toBe(false);
Особливості в контексті JS Core
inчасто використовується у циклахfor...in, що ітерують всі властивості, включаючи успадковані.hasOwnPropertyдопомагає уникнути небажаних властивостей, наприклад при копіюванні об’єктів.
Оптимізація, типові помилки та edge cases
- Не використовувати
hasOwnPropertyбез перевірки, що об’єкт не має власного методу з таким ім’ям (наприклад,obj.hasOwnProperty). У такому випадку треба викликати його черезObject.prototype.hasOwnProperty.call(obj, key). - Помилкове очікування, що
inне враховує прототипи; це часто приводить до помилок при перевірці конфігурацій.
Часті питання
- Чи можна замінити
hasOwnPropertyнаObject.prototype.hasOwnProperty.call(obj, key)? Так, це безпечніше. - Чому
for...inітерує прототипи? Тому що це частина специфікації ECMAScript.