instanceof
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
请注意,如果在创建对象后重新赋值 constructor.prototype(通常不建议这样做),instanceof 测试的值可能会发生变化。它也可以通过使用 Object.setPrototypeOf 更改 object 的原型来改变。
类也以同样的方式工作,因为类也具有 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 的行为。有关 instanceof 的确切算法,请参阅 Symbol.hasInstance 页面。
instanceof 和多领域
JavaScript 执行环境(窗口、框架等)各自都处于自己的*领域*中。这意味着它们具有不同的内置对象(不同的全局对象、不同的构造函数等)。这可能会导致意想不到的结果。例如,[] instanceof window.frames[0].Array 将返回 false,因为 Array.prototype !== window.frames[0].Array.prototype 并且当前领域的数组继承自前者。
这乍一看可能没有意义,但对于处理多个框架或窗口并通过函数将对象从一个上下文传递到另一个上下文的脚本来说,这将是一个有效且严重的问题。例如,你可以使用 Array.isArray() 安全地检查给定对象是否确实是一个 Array,而无需关心它来自哪个领域。
例如,要在不同上下文中检查 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
要测试一个对象是否不是特定构造函数的 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 分配为其原型。在这种情况下,如果你的代码从 x 中读取 C 的 私有字段,它仍然会失败。
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
}
为了避免这种情况,你可以通过向 C 添加 Symbol.hasInstance 方法来覆盖 instanceof 的行为,使其使用 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
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-relational-operators |
浏览器兼容性
加载中…