04. instanceof Operator

Вызов obj instanceof Constructor возвращает true, если объект принадлежит классу Constructor или классу, наследующему от него. Оператор instanceof требует, чтобы левым операндом был объект, а правым – имя класса объектов. Результатом оператора будет значение true, если объект, указанный слева, является экземпляром класса, указанного справа.

{} instanceof Object // => true
[] instanceof Array // => true
[] instanceof Object // => true

undefined instanceof Object // => false
null instanceof Object // => false
'abc' instanceof Object // => false
123 instanceof Object // => false

const d = new Date();
d instanceof Date;  // => true
d instanceof Object; // => true
d instanceof Number; //  => false

const a = [1, 2, 3];
a instanceof Array; // => true
a instanceof Object; // => true
a instanceof RegExp; // => false

Prototype chain and instanceof

Проверка происходит через сравнение прототипов. Сама по себе функция-конструктор не участвует в процессе проверки! Важна только цепочка прототипов для проверяемого объекта.

Алгоритм проверки obj instanceof Constructor:

  • Получить obj.__proto__

  • Сравнить obj.__proto__ с Constructor.prototype

  • Если не совпадает, тогда заменить obj на obj.__proto__ и повторить проверку на шаге 2 до тех пор, пока либо не найдется совпадение (результат true), либо цепочка прототипов не закончится (результат false).

Практически всегда для объектов выражение obj instanceof Object вернет true, поскольку объект имеет прототип Object.prototype. Однако, если объект был создан без прототипа, то нельзя проверить его тип:

> Object.create(null) instanceof Object
false
> Object.prototype instanceof Object
false

Однако typeof корректно распознает тип объекта:

> typeof Object.create(null)
'object'
> typeof Object.prototype
'object'

@@hasInstance symbol

A method with the key Symbol.hasInstance lets an object C customize the behavior of the instanceof operator. Signature of that method [Symbol.hasInstance](potentialInstance : any).

obj instanceof Type is equivalent to Type[Symbol.hasInstance](obj):

class Iterable {
  static [Symbol.hasInstance](obj) {
    return typeof obj[Symbol.iterator] === "function";
  }
}
let array = [1, 5, 5];
let string = "Welcome";
let number = 15;
array instanceof Iterable; // => true
string instanceof Iterable; // => true
number instanceof Iterable; // => false

x instanceof C works as follows in ES6:

  • If C is not an object, throw a TypeError.

  • If the method exists, call C[Symbol.hasInstance](x), coerce the result to boolean and return it.

  • Otherwise, compute and return the result according to the traditional algorithm (C must be callable, C.prototype in the prototype chain of x, etc.).

Особенности:

  • Позволяет делать собственные реализации проверки на instanceof

  • Эта проверка может находится внутри объекта (а не функции-конструктора)

Пример: объекты относятся к одному классу, если у них есть атрибут foo:

const obj = {
  foo: true,
  [Symbol.hasInstance](inst) {
    return Boolean("foo" in this) === Boolean("foo" in inst);
  }
};

const obj2 = {
  foo: false
};

obj2 instanceof obj;

Last updated