今天将延续这篇文章,借助一个老朋友——instanceof运算符,将经过它以及结合屡次讲的原型/原型链经典图来深刻理解原型/原型链。javascript
对于原始类型(primitive type)的值,即string
/number
/boolean
,你能够经过typeof
判断其类型,可是typeof
在判断到合成类型(complex type)的值的时候,返回值只有object
/function
,你不知道它究竟是一个object
对象,仍是数组,也不能判断出Object 下具体是什么细分的类型,好比 Array
、Date
、RegExp
、Error
等。java
官方对instanceof
运算符的解释是返回一个布尔值,表示对象是否为某个构造函数的实例。好比:git
function Foo() {}
var f1 = new Foo();
console.log(f1 instanceof Foo); // true
console.log(f1 instanceof Object); // true
复制代码
上面代码中,对象f1
是构造函数Foo
的实例,因此返回true
,可是“f1 instanceof Object”为何也是true
呢?github
至于为何等会再解释,先把instanceof
判断的规则告诉你们。根据以上代码看下图:数组
instanceof
运算符的左边是实例对象,右边是构造函数,左边变量暂称为A,右边变量暂称为B。它会检查右边构造函数的原型对象(prototype),是否在左边对象的原型链上。函数
通俗一点来说,instanceof
的判断规则是:instanceof
会检查整个原型链,将沿着A的__proto__
这条线来一直找,同时沿着B的prototype
这条线来一直找,直到能找到同一个引用,即同一个对象,那么就返回true
。若是找到终点还未重合,则返回false
。即上图中的 f1
-->__proto__
和 Foo
-->prototype
指向同一个对象,console.log(f1 instanceof Foo)
为true
。ui
按照以上规则,从新来看看“ f1 instanceof Object ”这句代码为何是true
? 根据上图很容易就能看出来, f1-->__proto__
-->__proto__
和Object
-->prototype
指向同一个对象,console.log(f1 instanceof Object)
为true
。spa
经过上面的规则,能够很好地解释一些比较怪异的现象,例如:prototype
console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true
console.log(Function instanceof Function); // true
console.log(Object instanceof Object); // true
复制代码
这些就是这篇文章所讲的看似很混乱的东西,如今知道为什么了吧。设计
但还有一种特殊状况,就是左边对象的原型链上,只有null
对象。这时,instanceof
判断会失真。
var obj = Object.create(null);
typeof obj // "object"
Object.create(null) instanceof Object // false
复制代码
上面代码中,Object.create(null)
返回一个新对象obj
,它的原型是null
(Object.create
后续会有专门文章介绍)。右边的构造函数Object
的prototype
属性,不在左边的原型链上,所以instanceof
就认为obj
不是Object
的实例。可是,只要一个对象的原型不是null
,instanceof
运算符的判断就不会失真。
说到这里,继续贴上这幅原型/原型链的经典图,是否如今看起来没那么复杂了呢。
若是这篇文章你看的比较仔细,再结合刚才介绍的instanceof
的概念规则,相信能看懂上面这张图的内容了。
那么问题又出来了。instanceof
这样设计,到底有什么用?到底instanceof
想表达什么呢?
这就要重点讲讲继承了,即instanceof
表示的就是一种继承关系,或者原型链的结构,请看后续文章介绍。
若是以为文章对你有些许帮助,欢迎在个人GitHub博客点赞和关注,感激涕零!