instanceof
表现
MDN 定义是 用于检测构造函数的 prototype 是否出现在某个实例对象的原型链上
基本格式: instanceObj instanceof constructor
js
let simStr = "this is simple string";
let myStr = new String();
let newStr = new String("Str created with constructor");
let myObj = {};
let myNonObj = Object.create(null);
let myDate = new Date();
console.log(simStr instanceof String); //false
console.log(myStr instanceof String); //true
console.log(newStr instanceof String); //true
console.log(myStr instanceof Object); //true
console.log(myObj instanceof Object); //true
console.log({} instanceof Object); //true
console.log(myNonObj instanceof Object); //false
console.log(myStr instanceof Date); //false
console.log(myDate instanceof Date); //true
console.log(myDate instanceof Object); //true
console.log(myDate instanceof String); //false
可见 instanceof 对于 new 实例化的需求还是很明显 这里的例外又是对象自己,字面量声明还是会被认为是 new 出来的实例
问题
js
console.log(myDate instanceof Date); //true
console.log(myDate instanceof Object); //true
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
let myCar = new Car("honda", "accord", 1998);
myCar instanceof Car;
myCar instanceof Object;
这里可以看出 instanceof 的主要问题/特点就是它判断原型链而非直接/父级原型,而 object 显然是所有对象的原型,所以用于做类型判断的精度/颗粒度不够
额外用法
判断不是实例时
js
if(!(myCar instanceof Car)){
....
}
// 不能够使用如下用法
if(!myCar instanceof Car){
...
}
// 因为myCar已经被转为布尔值,所以会永远报false
手动实现
js
function MyInstanceof(leftObj, rightObj) {
let rightProto = rightObj.prototype;
let leftProto = Object.getPrototypeOf(leftObj);
// 循环获取实例的下一格proto,知道实例的proto和原型的prototype相等或者为null结束
while (true) {
if (leftProto === null) {
return false;
}
if (leftProto === rightProto) {
return true;
}
leftProto = Object.getPrototypeOf(leftProto);
}
}
思路就是不断地获取实例对象的下一个 proto,并且判断是否和给定的原型 prototype 相等,直到相等或者发现实例的 proto 为 null