instanceof — JS

当 JavaScript 中,判断一个变量的品类尝尝会就此 typeof 运算符,在应用
typeof
运算符时采取引用类型存储值会面世一个题材,无论引用的凡啊项目的靶子,它还归
“object”。ECMAScript 引入了别样一个 Java 运算符 instanceof
来缓解是题材。instanceof 运算符与 typeof
运算符相似,用于识别正在处理的靶子的品类。与 typeof
方法不同之是,instanceof
方法要求开发者明确地肯定对象也有一定类型。例如:

清单 1. instanceof 示例

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

及时段代码问底凡“变量 oStringObject 是否也 String
对象的实例?”oStringObject 的确是 String
对象的实例,因此结果是”true”。尽管未像 typeof 方法那样灵活,但是以
typeof 方法返回 “object” 的情况下,instanceof 方法还是深有因此的。

nstanceof 运算符的健康用法

便来讲,使用 instanceof 就是判定一个实例是否属某种类型。例如:

清单 2. instanceof 常规用法

1
2
3
4
// 判断 foo 是否是 Foo 类的实例
function Foo(){}
var foo = new Foo();
console.log(foo instanceof Foo)//true

此外,更重的少数是 instanceof
可以于此起彼伏关系遇之所以来判定一个实例是否属于它们的父类型。例如:

清单 3. instanceof 当延续中涉嫌中的用法

1
2
3
4
5
6
7
8
// 判断 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 扑朔迷离用法

1
2
3
4
5
6
7
8
9
10
                
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
原型继承机制。

详尽剖析 ECMAScript-262 edition 3 中 instanceof 运算符的概念

言语专业针对中 instanceof 运算符的概念如下:

清单 5. 业内中 instanceof 运算符定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
                 
 11.8.6 The instanceof operator
 The production RelationalExpression:
     RelationalExpression instanceof ShiftExpression is evaluated as follows:
 
 1. Evaluate RelationalExpression.
 2. Call GetValue(Result(1)).// 调用 GetValue 方法得到 Result(1) 的值,设为 Result(2)
 3. Evaluate ShiftExpression.
 4. Call GetValue(Result(3)).// 同理,这里设为 Result(4)
 5. If Result(4) is not an object, throw a TypeError exception.// 如果 Result(4) 不是 object,
                                                                //抛出异常
 /* 如果 Result(4) 没有 [[HasInstance]] 方法,抛出异常。规范中的所有 [[...]] 方法或者属性都是内部的,
在 JavaScript 中不能直接使用。并且规范中说明,只有 Function 对象实现了 [[HasInstance]] 方法。
所以这里可以简单的理解为:如果 Result(4) 不是 Function 对象,抛出异常 */
 6. If Result(4) does not have a [[HasInstance]] method,
   throw a TypeError exception.
 // 相当于这样调用:Result(4).[[HasInstance]](Result(2))
 7. Call the [[HasInstance]] method of Result(4) with parameter Result(2).
 8. Return Result(7).
 
 // 相关的 HasInstance 方法定义
 15.3.5.3 [[HasInstance]] (V)
 Assume F is a Function object.// 这里 F 就是上面的 Result(4),V 是 Result(2)
 When the [[HasInstance]] method of F is called with value V,
     the following steps are taken:
 1. If V is not an object, return false.// 如果 V 不是 object,直接返回 false
 2. Call the [[Get]] method of F with property name "prototype".// 用 [[Get]] 方法取
                                                                // F 的 prototype 属性
 3. Let O be Result(2).//O = F.[[Get]]("prototype")
 4. If O is not an object, throw a TypeError exception.
 5. Let V be the value of the [[Prototype]] property of V.//V = V.[[Prototype]]
 6. If V is null, return false.
 // 这里是关键,如果 O 和 V 引用的是同一个对象,则返回 true;否则,到 Step 8 返回 Step 5 继续循环
 7. If O and V refer to the same object or if they refer to objects
   joined to each other (section 13.1.2), return true.
 8. Go to step 5.

上面的业内定义格外别扭,而且看起比较复杂,涉及到多定义,但将这段正式翻译成
JavaScript 代码却生粗略,如下:

清单 6. JavaScript instanceof 运算符代码

1
2
3
4
5
6
7
8
9
10
11
12
                
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
 var O = R.prototype;// 取 R 的显示原型
 L = L.__proto__;// 取 L 的隐式原型
 while (true) {
   if (L === null)
     return false;
   if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
     return true;
   L = L.__proto__;
 }
}

JavaScript 原型继承机制

鉴于本文主要汇集在解析 JavaScript instanceof 运算符,所以对于 JavaScript
的原型继承机制不再做详细的教授,下面参考来自
http://www.mollypages.org/misc/js.mp 的均等张图,此图片详细的叙说了
JavaScript 各种对象的来得和隐式原型链结构。

是因为该本文涉及显示原型和隐式原型,所以下面对当下片单概念发一下简说明。在
JavaScript 原型继承结构里,规范中用 [[Prototype]]
表示对象隐式的原型,在 JavaScript 中因故 __proto__ 表示,并且于
Firefox 和 Chrome 浏览器被是足以看获得此特性的,但是 IE 下十分。所有
JavaScript 对象还发 __proto__ 属性,但只有
Object.prototype.__proto__ 为 null,前提是从来不在 Firefox 或者 Chrome
下修改了之特性。这个特性指于它们的原型对象。 至于显示的原型,在
JavaScript 里用 prototype 属性表示,这个是 JavaScript
原型继承的基础知识,在此间就是非以讲述了。

图 1. JavaScript 原型链

 

教授 instanceof 复杂用法

出了方 instanceof 运算符的 JavaScript 代码和原型继承图,再来明
instanceof 运算符将易使反掌。下面用详细讲解 Object instanceof
Object,Function instanceof Function 和 Foo instanceof Foo
三单示范,其它示例读者可机关推演。

清单 7. Object instanceof Object

1
2
3
4
5
6
7
8
9
10
11
12
13
                
// 为了方便表述,首先区分左侧表达式和右侧表达式
ObjectL = Object, ObjectR = Object;
// 下面根据规范逐步推演
O = ObjectR.prototype = Object.prototype
L = ObjectL.__proto__ = Function.prototype
// 第一次判断
O != L
// 循环查找 L 是否还有 __proto__
L = Function.prototype.__proto__ = Object.prototype
// 第二次判断
O == L
// 返回 true

清单 8. Function instanceof Function

1
2
3
4
5
6
7
8
9
                
// 为了方便表述,首先区分左侧表达式和右侧表达式
FunctionL = Function, FunctionR = Function;
// 下面根据规范逐步推演
O = FunctionR.prototype = Function.prototype
L = FunctionL.__proto__ = Function.prototype
// 第一次判断
O == L
// 返回 true

清单 9. Foo instanceof Foo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    
// 为了方便表述,首先区分左侧表达式和右侧表达式
FooL = Foo, FooR = Foo;
// 下面根据规范逐步推演
O = FooR.prototype = Foo.prototype
L = FooL.__proto__ = Function.prototype
// 第一次判断
O != L
// 循环再次查找 L 是否还有 __proto__
L = Function.prototype.__proto__ = Object.prototype
// 第二次判断
O != L
// 再次循环查找 L 是否还有 __proto__
L = Object.prototype.__proto__ = null
// 第三次判断
L == null
// 返回 false

简析 instanceof 在 Dojo 继承机制被的行使

每当 JavaScript 中,是从未多又继承这个概念ECMAScript的,就像 Java 一样。但每当 Dojo
中采取 declare 声明类时,是允许继续自多只类似的。下面为 Dojo 1.6.1 为例。

清单 10. Dojo 中大多又继承

1
2
3
4
5
6
7
8
9
10
11
        
dojo.declare("Aoo",null,{});
dojo.declare("Boo",null,{});
dojo.declare("Foo",[Aoo,Boo],{});
 
var foo = new Foo();
console.log(foo instanceof Aoo);//true
console.log(foo instanceof Boo);//false
 
console.log(foo.isInstanceOf(Aoo));//true
console.log(foo.isInstanceOf(Boo));//true

点的言传身教中,Foo 同时继续自 Aoo 和 Boo,但当以 instanceof
运算符来检查 foo 是否是 Boo 的实例时,返回的是 false。实际上,在 Dojo
的里边,Foo 仍然只有持续自 Aoo,而经 mixin 机制把 Boo
类中的道以及性能拷贝到 Foo 中,所以当用 instanceof 运算符来检查是不是是
Boo 的实例时,会回 false。所以 Dojo 为每个接近的实例添加了一个初的办法为
isInstanceOf,用这个方法来检查多还继承