instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

语法

object instanceof constructor

参数

object
要检测的对象.
constructor
某个构造函数

描述

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

// 定义构造函数
function C(){} 
function D(){} 

var o = new C();


o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype


o instanceof D; // false,因为 D.prototype不在o的原型链上

o instanceof Object; // true,因为Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为C.prototype现在在o3的原型链上

需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。另外一种情况下,原表达式的值也会改变,就是改变对象obj的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的__proto__伪属性,是可以实现的。比如执行obj.__proto__ = {}之后,obj instanceof Foo就会返回false了。

instanceof和多全局对象(多个frame或多个window之间的交互)

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回false,因为 Array.prototype !== window.frames[0].Array.prototype,并且数组从前者继承。

起初,你会认为这样并没有意义,但是当你在你的脚本中开始处理多个frame或多个window以及通过函数将对象从一个窗口传到另一个窗口时,这就是一个有效而强大的话题。比如,实际上你可以通过使用 Array.isArray(myObj) 或者Object.prototype.toString.call(myObj) === "[object Array]"来安全的检测传过来的对象是否是一个数组。

比如检测一个Nodes在另一个窗口中是不是SVGElement,你可以使用myNode instanceof myNode.ownerDocument.defaultView.SVGElement

Mozilla开发者注意:
在代码中使用 XPCOM instanceof 有特殊影响: 如果查询接口成功执行后,obj instanceof xpcomInterface (e.g. Components.interfaces.nsIFile) 调用obj.QueryInterface(xpcomInterface) 并且返回 true 。这种调用的副作用是在一次成功的instanceof测试后,你可以在obj上使用xpcomInterface的属性。这与标准的JavaScript全局变量不同,即使obj来自不同的作用域, obj instanceof xpcomInterface也可以按预期产生作用。

示例

演示String对象和Date对象都属于Object类型和一些特殊情况

下面的代码使用了instanceof来证明:String和Date对象同时也属于Object类型(他们是由Object类派生出来的)。

但是,使用对象文字符号创建的对象在这里是一个例外:虽然原型未定义,但instanceof Object返回true。

var simpleStr = "This is a simple string"; 
var myString  = new String();
var newStr    = new String("String created with constructor");
var myDate    = new Date();
var myObj     = {};

simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
myString  instanceof String; // 返回 true
newStr    instanceof String; // 返回 true
myString  instanceof Object; // 返回 true

myObj instanceof Object;    // 返回 true, 尽管原型没有定义
({})  instanceof Object;    // 返回 true, 同上
myNonObj instanceof Object; // 返回 false, 一种创建对象的方法,这种方法创建的对象不是Object的一个实例

myString instanceof Date; //返回 false

myDate instanceof Date;     // 返回 true
myDate instanceof Object;   // 返回 true
myDate instanceof String;   // 返回 false

演示mycar属于Car类型的同时又属于Object类型

下面的代码创建了一个类型Car,以及该类型的对象实例mycar. instanceof运算符表明了这个mycar对象既属于Car类型,又属于Object类型。

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
var a = mycar instanceof Car;    // 返回 true
var b = mycar instanceof Object; // 返回 true

不是一个实例

要测试对象是否不是特定构造函数的实例,你可以这样做

if (!(mycar instanceof Car)) {
  // Do something, like mycar = new Car(mycar)
}

下面代码完全不同

if (!mycar instanceof Car)

这将永远是假的(!mycar将在instanceof之前被处理,所以你总是验证布尔值是否是Car的一个实例)。

规范

Specification Status Comment
ECMAScript Latest Draft (ECMA-262)
Relational Operators
Draft  
ECMAScript 2015 (6th Edition, ECMA-262)
Relational Operators
Standard  
ECMAScript 5.1 (ECMA-262)
The instanceof operator
Standard  
ECMAScript 3rd Edition (ECMA-262)
The instanceof operator
Standard Initial definition. Implemented in JavaScript 1.4.

浏览器兼容

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support Yes Yes1 Yes Yes Yes
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support Yes Yes Yes4 Yes Yes Yes

相关链接

文档标签和贡献者

最后编辑者: zhangchen,