“ 知其然而知其所以然,我们都知道instanceof 用来干嘛,那也应该要知道其实现原理”
01
—
instanceof用途
相信大多数人都用过instanceof 操作符,不扯淡,下面先简单说下基本使用方式和场景。
场景
当大家用到instanceof 的时候,大多数是你的typeof 已经不能满足要求了。typeof 在处理基本数据类型的时候还是没问题的,但是在判断引用类型的变量时,就显得力不从心了。
基本使用
console.log([] instanceof Array);//true
console.log([] instanceof Object);//true
console.log( ({}) instanceof Object );//true
console.log(typeof null);//"object"
console.log( null instanceof Object );//false
好,以上给出了instanceof 几个基本的使用方式,大伙看着基本上没毛病,那么问题来了:
-
为什么第1和第2行的结果是相同的?instanceof 到底是怎么实现的?
-
为什么第5行结果判断null是Object ,而第6行instanceof 说 null 又不是Object 类型。
带着这两个问题来看instanceof实现过程。
02
—
模拟instanceof实现原理
通过prototype来判断具体类型,并且通过函数的方式来进行模拟,c++底层是从其他方式来实现的。
// A instanceof B 模式A为left B为right
function myInstanceof(left, right){
//拿到left实例的__proto__属性(隐式原型)
var left_proto_ = left === null ? null : left.__proto__;
//拿到right的prototype属性(显式原型)
var rightProto = right.prototype;
//为什么要while语句???
while(true){
//兼容 null 的情况
if(left_proto_ === null){
return false;
}
//当隐式原型严格等于显式原型
if(left_proto_ === rightProto){
return true;
}
//这为什么要重新赋值???
left_proto_ = left_proto_.__proto__;
}
}
//测试
console.log(myInstanceof([], Array));//true
console.log(myInstanceof([], Object));//true
console.log(myInstanceof(null, Object));//false
看上面代码,表明了两处可能会让人比较疑惑的地方(第7行和第17行)。
这两行代码的原因主要是为解决上面引入的第一问,就是用来处理[]既是Array类型也是Object类型的情况,通过__proto_查找直到为null。
至于第二问中null 既是对象,而又不是对象类型的问题,其实是JavaScript设计中的一个bug。而站在原型链角度来理解,null 是原型链的顶端,自然用instanceof操作任意类型的变量都应该为false,这一点instanceof的逻辑是没有错的。
以上是个人对instanceof的一些理解,如有瑕疵,请斧正!!!
后续更新文章将第一时间更新在公众号中,欢迎关注!!!