Что возвращает instanceof при присваивании выражения в переменную?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Краткий ответ
instanceof всегда возвращает булево значение (true или false), независимо от того, используется ли оно напрямую или результат его выполнения присваивается переменной. При присваивания let result = expression instanceof Constructor в переменную result всегда попадёт логическое значение, результат проверки цепочки прототипов.
Подробное объяснение
instanceof — это бинарный оператор в JavaScript, который проверяет, присутствует ли конструктор Constructor в цепочке прототипов объекта expression. Его основная задача — определить принадлежность объекта к определённому классу или типу (с учётом наследования).
Ключевой момент: Оператор всегда возвращает boolean. Это его фундаментальное свойство, которое не меняется в зависимости от контекста использования.
Примеры и демонстрация
Рассмотрим классический пример:
class Animal {}
class Dog extends Animal {}
const myDog = new Dog();
// 1. Использование без присваивания
console.log(myDog instanceof Dog); // true
console.log(myDog instanceof Animal); // true (из-за наследования)
console.log(myDog instanceof Object); // true (все объекты в цепочке)
console.log(myDog instanceof Array); // false
// 2. Присваивание результата в переменную
const check1 = myDog instanceof Dog;
const check2 = myDog instanceof Array;
console.log(check1); // true (тип: boolean)
console.log(check2); // false (тип: boolean)
// 3. Проверка типа значения в переменной
console.log(typeof check1); // "boolean"
console.log(typeof check2); // "boolean"
Как работает instanceof под капотом?
Механизм можно упрощённо описать так:
- Оператор принимает левый операнд (проверяемый объект) и правый операнд (функцию-конструктор).
- Если левый операнд — примитив, сразу возвращается
false. - JavaScript проходит по цепочке прототипов объекта (
__proto__или[[Prototype]]), сравнивая каждый прототип сConstructor.prototype. - Если находит совпадение — возвращает
true, если доходит до конца цепочки (null) — возвращаетfalse.
Псевдокод алгоритма:
function customInstanceOf(obj, Constructor) {
if (obj === null || typeof obj !== 'object') {
return false;
}
let currentProto = Object.getPrototypeOf(obj);
while (currentProto !== null) {
if (currentProto === Constructor.prototype) {
return true;
}
currentProto = Object.getPrototypeOf(currentProto);
}
return false;
}
Важные нюансы и граничные случаи
1. Примитивы всегда возвращают false
console.log("строка" instanceof String); // false
console.log(42 instanceof Number); // false
console.log(true instanceof Boolean); // false
Это происходит потому, что примитивы не являются объектами (если не обёрнуты явно через new).
2. Объекты-обёртки
const strObj = new String("строка");
console.log(strObj instanceof String); // true
3. Переопределение @@hasInstance
Начиная с ES2015, можно переопределить поведение instanceof с помощью статического метода Symbol.hasInstance:
class MyClass {
static [Symbol.hasInstance](instance) {
return typeof instance === 'number';
}
}
const result = 42 instanceof MyClass; // Присваиваем в переменную
console.log(result); // true (хотя 42 — примитив-число)
console.log(typeof result); // "boolean" (всё равно boolean!)
4. Ложные срабатывания с Object.prototype
const plainObj = {};
console.log(plainObj instanceof Object); // true
5. Проблемы с фреймами и разными глобальными областями
// Если объект создан в одном iframe, а конструктор — в другом
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const ArrayFromIframe = iframe.contentWindow.Array;
const arr = new ArrayFromIframe();
console.log(arr instanceof Array); // false (!)
console.log(arr instanceof ArrayFromIframe); // true
Практическое применение в присваиваниях
Присваивание результата instanceof особенно полезно в:
- Условных конструкциях
const isArrayLike = obj instanceof Array || obj instanceof NodeList;
if (isArrayLike) {
// работаем как с коллекцией
}
- Валидации параметров функций
function processInput(input) {
const isValid = input instanceof HTMLInputElement;
if (!isValid) {
throw new TypeError('Ожидается элемент input');
}
// ... логика
}
- Фабриках и полиморфных функциях
function serialize(data) {
const isDate = data instanceof Date;
const isRegExp = data instanceof RegExp;
if (isDate) return data.toISOString();
if (isRegExp) return data.toString();
return JSON.stringify(data);
}
Итог
При присваивании let x = obj instanceof Constructor в переменную x всегда попадает булево значение — результат проверки наличия Constructor.prototype в цепочке прототипов obj. Это поведение соответствует спецификации ECMAScript и является неизменным фундаментальным свойством оператора, независимо от контекста его использования, переопределения Symbol.hasInstance или других факторов.