一、话题引入
上一篇文章笔者浅谈了一下JS原型链,在此我想再阐述一个观念,笔者认为:真要探究JS中Function与Object的具体关系的话,就像是去探究到底是鸡生蛋和蛋生鸡的关系,实际上我们很难确定这两者:到底谁是谁的实例,谁是谁的构造函数,因此这两个JS内的关键字应该是同级的关系,至于原因嘛:
很喜欢Linux创始人Linus Torvalds大佬的那句话:Talk is cheap. Show me the code.
为了方便大家理解,我在这里先引用一下MDN上instanceof的定义:
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
console.log(Object instanceof Function);
console.log(Function instanceof Object);
复制代码
看到这里,不知道各位心中是否已经输出了两行代码的结果,其实我刚才已经说明了结果,接下来请让我解释一下原因:
二、instanceof原理解析
我们当然没法创造出一个类似instanceof的内部关键字来实现这个功能,但是我们可以使用函数来模拟这个过程。
简单地讲,instanceof的原理就如定义所说:在检测对象的原型链上面查找构造函数的prototype属性是否出现,这个过程会沿着原型链一直找,直到找到原型链的最顶端Object.prototype还没找到,那就只能返回null了,说明该对象不是这个构造函数的实例.
// instance_of这个函数就是我们用来模拟instanceof功能的函数
// 它接收两个参数,第一个是检测的对象obj,第二个是检测的构造函数constructor
function instance_of(obj, constructor) {
let prototype = constructor.prototype;
// 这里使用了一个定义在Object上面的API => getPrototypeOf
// 它用于返回当前对象的原型的值
let proto = Object.getPrototypeOf(obj);
while(true) {
// 如果查找完整个原型链还找不到prototype属性那么就返回null
if(proto === null) {
return false;
}
// 这里就是对比当前原型对象上是否含有构造函数的prototype属性来判断结果,是则返回true循环结束
else if(proto === prototype) {
return true;
}
// 每一次循环都会返回当前对象的原型对象
// 第一次当然是返回传入参数obj的原型对象,往后就是原型链上的每一个对象
proto = Object.getPrototypeOf(proto);
}
}
// 我们可以观察自己模拟的方法instance_of和系统内的方法instanceof对于这两个关键字的测试结果
console.log(instance_of(Function, Object));
console.log(instance_of(Object, Function));
console.log(Function instanceof Object);
console.log(Object instanceof Function);
复制代码
至于四行输出的结果,当然是四个true了,大家可以到浏览器的控制台试一试效果
三、总结
以上内容就是笔者对于instanceof原理的理解了,如果哪里有什么问题,希望大佬们多多指正,感谢!