← Назад к вопросам

Что возвращает instanceof при присваивании выражения в переменную?

2.0 Middle🔥 152 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Краткий ответ

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 под капотом?

Механизм можно упрощённо описать так:

  1. Оператор принимает левый операнд (проверяемый объект) и правый операнд (функцию-конструктор).
  2. Если левый операнд — примитив, сразу возвращается false.
  3. JavaScript проходит по цепочке прототипов объекта (__proto__ или [[Prototype]]), сравнивая каждый прототип с Constructor.prototype.
  4. Если находит совпадение — возвращает 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 особенно полезно в:

  1. Условных конструкциях
const isArrayLike = obj instanceof Array || obj instanceof NodeList;

if (isArrayLike) {
  // работаем как с коллекцией
}
  1. Валидации параметров функций
function processInput(input) {
  const isValid = input instanceof HTMLInputElement;
  if (!isValid) {
    throw new TypeError('Ожидается элемент input');
  }
  // ... логика
}
  1. Фабриках и полиморфных функциях
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 или других факторов.

Что возвращает instanceof при присваивании выражения в переменную? | PrepBro