instanceof
Базовый уровень Широко доступен
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в различных версиях браузеров. Она доступна во всех браузерах с июля 2015 года.
Оператор instanceof проверяет, появляется ли свойство prototype конструктора где-либо в цепочке прототипов объекта. Возвращаемое значение — логическое (булево). Его поведение можно настроить с помощью Symbol.hasInstance.
Попробуйте
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car("Honda", "Accord", 1998);
console.log(auto instanceof Car);
// Expected output: true
console.log(auto instanceof Object);
// Expected output: true
Синтаксис
object instanceof constructor
Параметры
-
object - Объект для проверки.
-
constructor - Конструктор, с которым производится проверка.
Исключения
-
TypeError - Генерируется, если
constructorне является объектом. Еслиconstructorне имеет метода[Symbol.hasInstance](), он также должен быть функцией.
Описание
Оператор instanceof проверяет наличие constructor.prototype в цепочке прототипов object. Обычно (хотя не всегда) это означает, что object был сконструирован с помощью constructor.
// defining constructors
function C() {}
function D() {}
const o = new C();
// true, because: Object.getPrototypeOf(o) === C.prototype
o instanceof C;
// false, because D.prototype is nowhere in o's prototype chain
o instanceof D;
o instanceof Object; // true, because:
C.prototype instanceof Object; // true
// Re-assign `constructor.prototype`: you should
// rarely do this in practice.
C.prototype = {};
const o2 = new C();
o2 instanceof C; // true
// false, because C.prototype is nowhere in
// o's prototype chain anymore
o instanceof C;
D.prototype = new C(); // add C to [[Prototype]] linkage of D
const o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true since C.prototype is now in o3's prototype chain
Обратите внимание, что значение проверки instanceof может измениться, если constructor.prototype переназначается после создания объекта (что обычно не рекомендуется). Его также можно изменить, изменив прототип object с помощью Object.setPrototypeOf.
Классы ведут себя так же, потому что классы также имеют свойство prototype.
class A {}
class B extends A {}
const o1 = new A();
// true, because Object.getPrototypeOf(o1) === A.prototype
o1 instanceof A;
// false, because B.prototype is nowhere in o1's prototype chain
o1 instanceof B;
const o2 = new B();
// true, because Object.getPrototypeOf(Object.getPrototypeOf(o2)) === A.prototype
o2 instanceof A;
// true, because Object.getPrototypeOf(o2) === B.prototype
o2 instanceof B;
Для связанных функций, instanceof ищет свойство prototype в целевой функции, поскольку связанные функции не имеют prototype.
class Base {}
const BoundBase = Base.bind(null, 1, 2);
console.log(new Base() instanceof BoundBase); // true
instanceof и Symbol.hasInstance
Если constructor имеет метод Symbol.hasInstance, этот метод будет вызван в первую очередь, с object в качестве единственного аргумента и constructor в качестве this.
// This class allows plain objects to be disguised as this class's instance,
// as long as the object has a particular flag as its property.
class Forgeable {
static isInstanceFlag = Symbol("isInstanceFlag");
static [Symbol.hasInstance](obj) {
return Forgeable.isInstanceFlag in obj;
}
}
const obj = { [Forgeable.isInstanceFlag]: true };
console.log(obj instanceof Forgeable); // true
Поскольку все функции наследуют от Function.prototype по умолчанию, в большинстве случаев метод Function.prototype[Symbol.hasInstance]() определяет поведение instanceof, когда правая часть является функцией. См. страницу Symbol.hasInstance для получения точного алгоритма instanceof.
instanceof и множественные области
Среды выполнения JavaScript (окна, фреймы и т. д.) находятся каждая в своей собственной области (realm). Это означает, что у них разные встроенные объекты (разные глобальные объекты, разные конструкторы и т. д.). Это может привести к неожиданным результатам. Например, [] instanceof window.frames[0].Array вернет false, потому что Array.prototype !== window.frames[0].Array.prototype и массивы в текущей области наследуются от первого.
Поначалу это может показаться бессмысленным, но для скриптов, работающих с несколькими фреймами или окнами и передающих объекты из одного контекста в другой с помощью функций, это будет серьезной проблемой. Например, вы можете безопасно проверить, является ли данный объект на самом деле массивом, используя Array.isArray(), независимо от того, из какой области он получен.
Например, чтобы проверить, является ли Node объектом SVGElement в другом контексте, вы можете использовать myNode instanceof myNode.ownerDocument.defaultView.SVGElement.
Примеры
Использование instanceof со String
Следующий пример демонстрирует поведение instanceof с объектами String.
const literalString = "This is a literal string";
const stringObject = new String("String created with constructor");
literalString instanceof String; // false, string primitive is not a String
stringObject instanceof String; // true
literalString instanceof Object; // false, string primitive is not an Object
stringObject instanceof Object; // true
stringObject instanceof Date; // false
Использование instanceof с Map
Следующий пример демонстрирует поведение instanceof с объектами Map.
const myMap = new Map(); myMap instanceof Map; // true myMap instanceof Object; // true myMap instanceof String; // false
Объекты, созданные с помощью Object.create()
Следующий пример демонстрирует поведение instanceof с объектами, созданными с помощью Object.create().
function Shape() {}
function Rectangle() {
Shape.call(this); // call super constructor.
}
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
const rect = new Rectangle();
rect instanceof Object; // true
rect instanceof Shape; // true
rect instanceof Rectangle; // true
rect instanceof String; // false
const literalObject = {};
const nullObject = Object.create(null);
nullObject.name = "My object";
literalObject instanceof Object; // true, every object literal has Object.prototype as prototype
({}) instanceof Object; // true, same case as above
nullObject instanceof Object; // false, prototype is end of prototype chain (null)
Демонстрация того, что myCar относится к типу Car и типу Object
Следующий код создает тип объекта Car и экземпляр этого типа объекта, myCar. Оператор instanceof демонстрирует, что объект myCar относится к типу Car и к типу Object.
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const myCar = new Car("Honda", "Accord", 1998);
const a = myCar instanceof Car; // returns true
const b = myCar instanceof Object; // returns true
Не является экземпляром
Чтобы проверить, не является ли объект instanceof конкретного конструктора, вы можете сделать следующее:
if (!(myCar instanceof Car)) {
// Do something, like:
// myCar = new Car(myCar)
}
Это сильно отличается от:
if (!myCar instanceof Car) {
// unreachable code
}
Это всегда будет false. (!myCar будет вычислен перед instanceof, поэтому вы всегда пытаетесь узнать, является ли логическое значение экземпляром Car).
Переопределение поведения instanceof
Распространенная ошибка при использовании instanceof — полагать, что, если x instanceof C, то x был создан с использованием C в качестве конструктора. Это не так, потому что x может быть напрямую назначен с C.prototype в качестве его прототипа. В этом случае, если ваш код считывает закрытые поля C из x, он все равно завершится ошибкой:
class C {
#value = "foo";
static getValue(x) {
return x.#value;
}
}
const x = { __proto__: C.prototype };
if (x instanceof C) {
console.log(C.getValue(x)); // TypeError: Cannot read private member #value from an object whose class did not declare it
}
Чтобы избежать этого, вы можете переопределить поведение instanceof, добавив метод Symbol.hasInstance к C, чтобы он выполнял брендированную проверку с помощью in:
class C {
#value = "foo";
static [Symbol.hasInstance](x) {
return #value in x;
}
static getValue(x) {
return x.#value;
}
}
const x = { __proto__: C.prototype };
if (x instanceof C) {
// Doesn't run, because x is not a C
console.log(C.getValue(x));
}
Обратите внимание, что вы можете захотеть ограничить это поведение текущим классом; в противном случае это может привести к ложным срабатываниям для подклассов:
class D extends C {}
console.log(new C() instanceof D); // true; because D inherits [Symbol.hasInstance] from C
Вы можете сделать это, проверив, что this является текущим конструктором:
class C {
#value = "foo";
static [Symbol.hasInstance](x) {
return this === C && #value in x;
}
}
class D extends C {}
console.log(new C() instanceof D); // false
console.log(new C() instanceof C); // true
console.log({ __proto__: C.prototype } instanceof C); // false
Спецификации
Совместимость с браузерами
| Desktop | Mobile | Server | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
instanceof |
1 |
12 |
1 |
4 |
1 |
18 |
4 |
10.1 |
1 |
1.0 |
4.4 |
1 |
1.0.0 |
1.0 |
0.10.0 |
Смотрите также
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof