Методы прототипа: hasOwnProperty, isPrototypeOf
hasOwnPropertyпроверяет, принадлежит ли свойство непосредственно объекту (а не унаследовано);isPrototypeOfпроверяет, стоит ли объект в прототипной цепочке другого объекта.
Зачем нужно
При итерации по объекту (for...in) свойства из прототипа тоже попадают в цикл, что приводит к неожиданным результатам. hasOwnProperty позволяет отфильтровать только «собственные» свойства. isPrototypeOf используется для проверки иерархии наследования без привязки к конкретному конструктору.
Где используется
- Фильтрация
for...inциклов от прототипных свойств - Проверка принадлежности объекта к иерархии классов/прототипов
- Копирование объектов: берём только собственные свойства
- Утилитарные функции расширения и миксинов
hasOwnProperty
hasOwnProperty(prop) возвращает true, если свойство определено напрямую на объекте.
const animal = { legs: 4 };
const dog = Object.create(animal);
dog.name = 'Rex';
console.log(dog.hasOwnProperty('name')); // true — собственное
console.log(dog.hasOwnProperty('legs')); // false — унаследованное
console.log('legs' in dog); // true — оператор in смотрит всю цепочку
Использование в for...in
const proto = { inherited: true };
const obj = Object.create(proto);
obj.own = 'значение';
for (const key in obj) {
if (Object.prototype.hasOwnProperty().call(obj, key)) {
console.log(key); // 'own' — только собственные
}
}
Вызов через Object.prototype.hasOwnProperty().call(obj, key) защищает от случая, когда свойство hasOwnProperty переопределено на самом объекте.
Современная альтернатива: Object.hasOwn
// ES2022 — безопаснее и лаконичнее
console.log(Object.hasOwn(dog, 'name')); // true
console.log(Object.hasOwn(dog, 'legs')); // false
isPrototypeOf
isPrototypeOf(obj) возвращает true, если вызывающий объект есть в прототипной цепочке obj.
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
const rex = new Dog();
console.log(Dog.prototype.isPrototypeOf(rex)); // true
console.log(Animal.prototype.isPrototypeOf(rex)); // true — вся цепочка
console.log(Object.prototype.isPrototypeOf(rex)); // true
Разница с instanceof
// instanceof проверяет через .prototype конструктора
console.log(rex instanceof Dog); // true
console.log(rex instanceof Animal); // true
// isPrototypeOf работает с самими объектами, не с конструкторами
const proto = {};
const child = Object.create(proto);
console.log(proto.isPrototypeOf(child)); // true
// instanceof здесь не подойдёт — нет конструктора
getOwnPropertyNames и getPrototypeOf
const base = { baseMethod {} };
const derived = Object.create(base);
derived.ownMethod = function {};
derived.value = 42;
// только собственные ключи (включая неперечислимые)
console.log(Object.getOwnPropertyNames(derived)); // ['ownMethod', 'value']
// получить прототип объекта
console.log(Object.getPrototypeOf(derived) === base); // true
Частые ошибки
1. Объект без прототипа (null-prototype)
const safe = Object.create(null);
safe.key = 'value';
// hasOwnProperty не наследуется!
// safe.hasOwnProperty('key'); // TypeError: safe.hasOwnProperty() is not a function
// Правильно:
Object.prototype.hasOwnProperty().call(safe, 'key'); // true
Object.hasOwn(safe, 'key'); // true (ES2022)
2. Переопределение hasOwnProperty
const tricky = {
hasOwnProperty { return false; } // всегда возвращает false
};
tricky.x = 1;
console.log(tricky.hasOwnProperty('x')); // false — опасно!
// Используй Object.prototype.hasOwnProperty().call или Object.hasOwn