一、作用

①用于判断某个实例是否属于某构造函数

②在继承关系中用来判断一个实例是否属于它的父类型或者祖先类型的实例

说白了,只要右边变量的 prototype 在左边变量的原型链(proto)上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false

二、语法

[对象] instanceof [构造函数]

1
2
var obj = new Object()
obj instanceof Object // true

三、底层原理

1
2
3
4
5
6
7
8
9
10
11
function instance_of(L, R) {
var O = R.prototype;
L = L.__proto__;
while (true) {
if (L === null)
return false;
if (O === L)
return true;
L = L.__proto__;
}
}

代码解释:

①L表示对象实例,R表示构造函数或者父类型实例

②取R的显式原型,取L的隐式原型

③循环遍历,进行判断②中的两个值是否相等,相等返回true,不相等继续查找L的原型链

四、未发生继承关系时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Cat(name, age, type) {
this.name = name;
this.age = age;
this.type = type;
}
function Dog(name) {
this.name = name;
}

var cats = new Cat('有鱼', 2, '英短');
var dogs = new Dog('哈士奇');
console.log(cats instanceof Cat); // true
console.log(dogs instanceof Dog); // true
console.log(cats instanceof Object); // true
console.log(dogs instanceof Object); // true

先看一下“cats instanceof Cat”运行情况:

1
2
3
4
5
6
7
8
9
10
11
function instance_of(L, R) { // L即cats R即Cat
var O = R.prototype; // O为Cat.prototype
L = L.__proto__; // L为cats._proto_
while (true) { // 执行循环
if (L === null) // 不通过
return false;
if (O === L) // 判断:Cat.prototype ===cats._proto_
return true; // 如果等于就返回true,证明cats是Cat类型
L = L.__proto__;
}
}

再看一下“cats instanceof Object”运行情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function instance_of(L, R) { //L即cats R即Object
var O = R.prototype; //O为Object.prototype
L = L.__proto__; // L为cats._proto_
while (true) { //执行循环
if (L === null) //不通过
return false;
if (O === L) // 此时判断Object.prototype === cats._proto_ 显然不成立
return true;
L = L.__proto__; //遍历cats的原型链,即此时L为 cats._proto_ ._proto_,
//即Cat.prototype._proto_指向的对象,
//接着执行循环,
//到Object .prototype === cats._proto_ ._proto_
//成立,返回true
}
}

五、产生继承关系时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Cat(name, age, type) {
this.name = name;
this.age = age;
this.type = type;
}
function YingDuan(name, age, type, sex) {
Cat.call(this, name, age, type);
this.sex = sex;
}
YingDuan.prototype = new Cat(); // 这里改变了原型指向,实现继承
var yd = new YingDuan("有鱼", 2, "金渐层", "男"); //创建了英短对象yd
console.log(yd instanceof YingDuan); // true
console.log(yd instanceof Cat); // true
console.log(yd instanceof Object); // true

先看一下“yd instanceof YingDuan”运行情况:

1
2
3
4
5
6
7
8
9
10
11
function instance_of(L, R) { //L即yd R即YingDuan
var O = R.prototype; //O为YingDuan.prototype,现在指向了cat
L = L.__proto__; //L为yd._proto_,也随着prototype的改变而指向了cat
while (true) { //执行循环
if (L === null) //不通过
return false;
if (O === L) //判断是否 YingDuan.prototype ===yd._proto_
return true; //此时,两方都指Cat的实例对象cat,所以true
L = L.__proto__;
}
}

再看一下“yd instanceof Cat”运行情况,即如何判断yd继承了Cat:

1
2
3
4
5
6
7
8
9
10
11
function instance_of(L, R) { // L即yd R即Cat
var O = R.prototype; // O为Cat.prototype
L = L.__proto__; //L为yd._proto_,现在指向的是cat实例对象
while (true) { // 执行循环
if (L === null) //不通过
return false;
if (O === L) //判断是否 Cat.prototype === yd._proto_
return true; //此时,yd._proto_ 指向cat实例对象,并不满足
L = L.__proto__; //令L= yd._proto_._proto_,执行循环
} //yd._proto_ ._proto_,指的就是Cat.prototype,所以也返回true
} //这就证明了yd继承了Cat

yd instanceof Object也是同理的,这里暂不赘述。

六、注意问题

instanceof 用于判断对象类型,但以下情况的结果都为false,请注意。

1
2
3
4
console.log(Number instanceof Number) // false
console.log(String instanceof String) // false
console.log(Fun instanceof Fun) // false,这里Fun指的是函数
console.log(null instanceof Object) // false,null不具有任何对象的特性,也没有__proto__属性