首页 > 代码库 > instanceof

instanceof

instanceof 运算符简介

在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。例如:

清单 1. instanceof 示例
 var oStringObject = new String("hello world"); 
 console.log(oStringObject instanceof String); 	 // 输出 "true"

这段代码问的是“变量 oStringObject 是否为 String 对象的实例?”oStringObject 的确是 String 对象的实例,因此结果是"true"。尽管不像 typeof 方法那样灵活,但是在 typeof 方法返回 "object" 的情况下,instanceof 方法还是很有用的。

instanceof 运算符的常规用法

通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。例如:

清单 2. instanceof 常规用法
 // 判断 foo 是否是 Foo 类的实例
 function Foo(){} 
 var foo = new Foo(); 
 console.log(foo instanceof Foo)//true

另外,更重的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。例如:

清单 3. instanceof 在继承中关系中的用法
 // 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
 function Aoo(){} 
 function Foo(){} 
 Foo.prototype = new Aoo();//JavaScript 原型继承

 var foo = new Foo(); 
 console.log(foo instanceof Foo)//true 
 console.log(foo instanceof Aoo)//true

上面的代码中是判断了一层继承关系中的父类,在多层继承关系中,instanceof 运算符同样适用。

你真的了解 instanceof 操作符吗?

看了上面的代码示例,是不是觉得 instanceof 操作符很简单,下面来看点复杂的用法。

清单 4. instanceof 复杂用法
 console.log(Object instanceof Object);//true 
 console.log(Function instanceof Function);//true 
 console.log(Number instanceof Number);//false 
 console.log(String instanceof String);//false 

 console.log(Function instanceof Object);//true 

 console.log(Foo instanceof Function);//true 
 console.log(Foo instanceof Foo);//false

看了上面的代码是不是又晕头转向了?为什么 Object 和 Function instanceof 自己等于 true,而其他类 instanceof 自己却又不等于 true 呢?如何解释?要想从根本上了解 instanceof 的奥秘,需要从两个方面着手:1,语言规范中是如何定义这个运算符的。2,JavaScript 原型继承机制。

01 ECMASCRIPT 5.1 Standard文档中的定义:
02 11.8.6 The instanceof operator
03  
04 The production RelationalExpression : RelationalExpression instanceof ShiftExpression is evaluated as follows:
05  
06 1.Let lref be the result of evaluating RelationalExpression.
07 2.Let lval be GetValue(lref).
08 3.Let rref be the result of evaluating ShiftExpression.
09 4.Let rval be GetValue(rref).
10 5.If Type(rval) is not Object, throw a TypeError exception.
11 6.If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
12 7.Return the result of calling the [[HasInstance]] internal method of rval with argument lval.
13  
14 15.3.5.3 [[HasInstance]] (V)
15  
16 Assume F is a Function object.
17  
18 When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:
19  
20 //V不是对象,直接返回false
21 1.If V is not an object, return false.
22  
23 //用 [[Get]] 方法取 F方法的prototype属性,结果赋值给O
24 2.Let O be the result of calling the [[Get]] internal method of F with property name "prototype".
25  
26 //如果O不是一个对象,报告异常
27 3.If Type(O) is not Object, throw a TypeError exception.
28  
29 //重复循环
30 4.Repeat
31     //V = V.[[Prototype]]
32     a.Let V be the value of the [[Prototype]] internal property of V.
33     b.If V is null, return false.
34     c.If O and V refer to the same object, return true.
35  
36 NOTE Function objects created using Function.prototype.bind have a different implementation of [[HasInstance]] defined in 15.3.4.5.3.

对应上述规范做个函数模拟A instanceof B:

01 function _instanceof(A, B) {
02     var O = B.prototype;// 取B的显示原型
03     A = A.__proto__;// 取A的隐式原型
04     while (true) { 
05         //Object.prototype.__proto__ === null
06         if (A === null
07             return false
08         if (O === A)// 这里重点:当 O 严格等于 A 时,返回 true 
09             return true
10         A = A.__proto__;
11     }
12 }

使用此函数模拟解析过程:

view source
 
01 Object instanceof Object解析,执行_instanceof (Object, Object)
02 O = Object.prototype;
03 A = Object.__proto__ = Function.prototype
04 A = Function.prototype.__proto__ = Object.prototype
05 return true;
06  
07 Function instanceof Function解析,执行_instanceof (Function, Function)
08 O = Function.prototype;
09 A = Function.__proto__ = Function.prototype;
10 return true;
11  
12 Function instanceof Object解析,执行_instanceof (Function, Object)
13 O = Object.prototype;
14 A = Function.__proto__ = Function.prototype;
15 A = Function.prototype.__proto__ = Object.prototype;
16 return true;
17  
18 String instanceof String解析,执行_instanceof (String, String)
19 O = String.prototype;
20 A = String.__proto__ = Function.prototype;
21 A = Function.prototype.__proto__ = Object.prototype;
22 A = Object.prototype.__proto__ = null;
23 return false;
24  
25 Ben instanceof Ben解析,执行_instanceof (Ben, Ben)
26 O = Ben.prototype;
27 A = Ben.__proto__ = Ben.prototype;
28 A = Ben.prototype.__proto__ = Object.prototype;
29 A = Object.prototype.__proto__ = null;
30 return false;

 

instanceof