Оператор instanceof
instanceofпроверяет, присутствует лиprototypeконструктора в прототипной цепочке объекта, возвращаяtrueилиfalse.
Зачем нужно
instanceof позволяет проверять тип объекта в рантайме: является ли объект экземпляром конкретного класса или его потомка. Это важно при написании полиморфного кода, обработке ошибок и работе с иерархиями классов.
Где используется
- Проверка типа ошибки в
catch-блоке - Полиморфизм: разное поведение для разных типов
- Валидация аргументов функций
- Паттерн Visitor
Базовый синтаксис
class Animal {}
class Dog extends Animal {}
const rex = new Dog();
console.log(rex instanceof Dog); // true
console.log(rex instanceof Animal); // true — проверяет всю цепочку
console.log(rex instanceof Object); // true — Object в вершине цепочки
console.log(rex instanceof Array); // false
Как работает
instanceof проходит по [[Prototype Pattern]]-цепочке объекта слева и сравнивает каждое звено с Constructor.prototype:
// Эквивалент instanceof вручную
function myInstanceOf(obj, Constructor) {
let proto = Object.getPrototypeOf(obj);
while (proto !== null) {
if (proto === Constructor.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
}
console.log(myInstanceOf(rex, Dog)); // true
console.log(myInstanceOf(rex, Animal)); // true
Проверка типов ошибок
function processError(err) {
if (err instanceof TypeError) {
console.error('Ошибка типа:', err.message);
} else if (err instanceof RangeError) {
console.error('Выход за диапазон:', err.message);
} else if (err instanceof Error) {
console.error('Общая ошибка:', err.message);
}
}
try {
null.property; // TypeError
} catch (e) {
processError(e); // 'Ошибка типа: Cannot read properties of null'
}
Использование с пользовательскими классами
class Shape {
area { return 0; }
}
class Circle extends Shape {
constructor(r) { super; this.r = r; }
area { return Math.PI * this.r ** 2; }
}
class Rectangle extends Shape {
constructor(w, h) { super; this.w = w; this.h = h; }
area { return this.w * this.h; }
}
function printArea(shape) {
if (!(shape instanceof Shape)) {
throw new TypeError('Ожидается экземпляр Shape');
}
console.log(`Площадь: ${shape.area.toFixed(2)}`);
}
printArea(new Circle(5)); // Площадь: 78.54
printArea(new Rectangle(3, 4)); // Площадь: 12.00
Symbol.hasInstance — кастомизация
class EvenNumber {
static [Symbol.hasInstance](value) {
return typeof value === 'number' && value % 2 === 0;
}
}
console.log(2 instanceof EvenNumber); // true
console.log(3 instanceof EvenNumber); // false
console.log(42 instanceof EvenNumber); // true
Частые ошибки
1. Разные realm'ы (iframe, vm)
// Объект, созданный в iframe, может не пройти instanceof
// из основного документа, даже если класс одинаковый
const arr = new iframe.contentWindow.Array;
arr instanceof Array; // false! Разные Array.prototype
// Для проверки встроенных типов используй:
Array.isArray(arr); // true — не зависит от realm
Object.prototype.toString().call(arr); // '[object Array]'
2. instanceof с примитивами
console.log('строка' instanceof String); // false — примитив, не объект
console.log(42 instanceof Number); // false
// typeof для примитивов:
typeof 'строка' === 'string'; // true
3. Изменение prototype после создания объекта
function Foo() {}
const obj = new Foo();
Foo.prototype = {}; // заменили прототип!
console.log(obj instanceof Foo); // false — цепочка разорвана
Связанные темы
- Прототипная цепочка
- Методы прототипа -- hasOwnProperty, isPrototypeOf
- Типы ошибок -- Error, TypeError, ReferenceError
- _MOC ООП
- _MOC JavaScript