前言
在实际的开发中,经常会遇到这种场景: 判断一个实例对对象是否为一个类的实例,这个时候我们有两种解决方法:即 instanceof
和constructor
,前者指出对象是否为类/类的原型链上的一个实例,后者表示创建实例对象的构造函数。
instanceOf 实现
instanceOf 介绍
MDN中的定义介绍
通俗点理解就是: instanceOf用来判断一个实例是否在某个类的原型链上的任何位置,返回值是一个布尔值。
instanceOf 使用
function constructorFunB() {
console.log('这是一个构造函数B');
}
function constructorFunC() {
console.log('这是一个构造函数C');
}
const instanceObj = new constructorFunA();
constructorFunC.prototype = constructorFunA.prototype;
console.log(instanceObj instanceof constructorFunA); // true
console.log(instanceObj instanceof constructorFunB); // false
console.log(instanceObj instanceof constructorFunC); // true
console.log(instanceObj instanceof Object); // true
上述代码中,为什么除constructorFunB,其余的打印都是true呢? 而constructorFunB又为什么打印为false呢?
- constructorFunA
constructorFunA很好理解,通过new constructorFunA 得到的instanceObj, instanceObj是构造函数constructorFunA的实例对象,当然返回true
-
constructorFunB, 由于constructorFunB和constructorFunA没有任何的联系,也不在同一条原型链上,所以返回false
-
constructorFunC, 由于constructorFunC.prototype = constructorFunA.prototype,使得constructorFunC和constructorFunA的原型对象相同,所有返回true
-
Object, 由于原型链的顶端就是Object.prototype, 所以也会返回true
instanceOf 实现
根据上述的具体使用,可以得知,instanceOf的原理其实就是判断实例对象的__proto__ 是否等于构造函数的prototype
,如果不等于,则会再它原型链上寻找,直到找到Object.prototype/null,根据找到的位置结果,返回最终的布尔值。
下面看具体的代码实现
function myInstanceOf(objInstance, constructorFun){
const constructorFunPro = constructorFun.prototype;
let objInstanceProto = objInstance.__proto__;
while(true){
// 原型链顶部还未找到,则返回false
if(!objInstanceProto){
return false;
}
if(objInstanceProto === constructorFunPro){
return true;
}
// 当前原型对象不符合,则继续再原型对象的原型上继续查找
constructorFunPro = constructorFunPro.__proto__
}
}
总结
constructor
更加精确地指向对象所属的类,而对 instanceof
而言,即使是父类也会返回 true
。
所以需要精确判断对象所属的累,建议使用constructor
。