在探究instanceof之前,先简单复习一下原型链的知识
原型链图
①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象(Object)
③所有引用类型的__proto__属性指向它构造函数的prototype
接下来我们来看一下几道题目
function Aoo(){}
function Foo(){}
Foo.prototype = new Aoo();
var foo = new Foo();
console.log(foo instanceof Foo)
console.log(foo instanceof Aoo)
根据刚才的原型链图和上述代码,我们画一下简单的相关原型链
由于Foo.prototype = new Aoo(),所以Foo的原型对象变成了Aoo的一个实例对象,其隐式原型就指向了Aoo的显示原型,具体情况见下图的红色箭头。
instanceof
那么问题来了,instanceof是什么呢。
在JS中,判断一个变量的类型,常常会用到typeof运算符,但当用来判断引用类型变量时,无论是什么类型的变量,它都会返回Object。为此,引入了instanceof。
instanceof的内部实现机制是通过判断对象的原型链上是否能找到对象的 prototype。
这样讲还是过于抽象化,我们可以这样来理解
A instanceof B
我们现在就是要判断 A的原型链,能否经过B的prototype。
我们再一次回到上一道题,来看看两个instanceof是怎么执行的
foo instanceof Foo
foo为A,Foo为B,那么
第一步,Foo先找到自己的prototype,然后停下,不动了。
第二步,foo开始寻找自己的原型链,实例对象通过隐式原型去寻找自己的原型链。
第三步,从图中可以看到,两个绿色的过程步骤交汇在了Foo的prototype。那么说明foo就是Foo的一个实例对象,所以结果返回为true。
再来看一下第二题
console.log(foo instanceof Aoo)
这次的B是Aoo,那么一样的步骤,先找到Aoo的prototype,然后重复上述步骤
返回结果为true。
例题
console.log(Object instanceof Object) //true
console.log(Function instanceof Function) //true
console.log(Function instanceof Object) //true
console.log(Foo instanceof Function) //true
console.log(Foo instanceof Foo) //false
依旧需要图解
这里稍微解释一下,Object本身也是一个函数对象,那么它的隐式原型自然也就指向函数Function的prototype。
同时,任何函数的prototype又是一个Object对象,其隐式原型又指向了Object的prototype。
所以就形成了下面的链图。
再补充一点,Function本身也是一个函数对象,所以其隐式原型就是它自己