前端面试系列-JS篇--一场探寻 instanceof 奥秘的奇幻之旅 🌈
大家好,我是你们的博客导游!今天,我们要一起踏上一场关于instanceof
的奇幻之旅。在这趟旅程中,我们将探讨instanceof
的介绍、原理、手写实现、测试以及应用场景等各方面的内容。请系好安全带,我们这就出发!
1. instanceof
,它到底是个啥?🤔
说起instanceof
,它可是 JavaScript 中的一个重要运算符。它用于判断一个对象是否是某个构造函数的实例。简单来说,instanceof
就像是一把神奇的尺子,可以帮我们量出对象与构造函数之间的亲密关系。
class Dog {
constructor(name) {
this.name = name;
}
}
const myDog = new Dog('Buddy');
console.log(myDog instanceof Dog); // true
console.log(myDog instanceof Object); // true
2. instanceof
的原理:揭开神秘面纱 🕵️♀️
要弄清楚instanceof
的原理,我们得先了解一下 JavaScript 中的原型链。每个对象都有一个原型(prototype),通过__proto__
属性可以找到它。当我们试图访问一个对象的属性时,如果对象本身没有这个属性,那么 JavaScript 将会沿着原型链往上寻找。
而instanceof
运算符的工作原理,就是沿着原型链一路向上找,看看左侧的对象的原型链中是否有右侧构造函数的prototype
。
3. 手写instanceof
:仿佛回到了石器时代 🔨
知道了 instanceof
的原理,我们来尝试一下手写一个 myInstanceOf
函数,让它能够完成与 instanceof
相同的功能。
function myInstanceOf(left, right) {
// 验证输入的有效性
if (typeof left !== 'object' || left === null) return false;
// 获取目标构造函数的原型
const prototype = right.prototype;
// 获取实例对象的原型
let leftProto = left.__proto__;
// 遍历实例对象的原型链
while (true) {
// 如果遍历完整个原型链仍未找到目标构造函数的原型,返回 false
if (leftProto === null) return false;
// 当找到目标构造函数的原型,返回 true
if (leftProto === prototype) {
return true;
}
// 如果没找到,继续向上查找原型链
leftProto = leftProto.__proto__;
}
}
由于 instanceof
运算符要检测的是某个对象是否是某个构造函数的实例,因此需要先进行一个前置判断条件,即判断 left 是否为对象类型,如果不是对象类型则直接返回 false。这是因为只有对象才有原型链的概念,基本数据类型没有原型链,不能使用 instanceof
运算符进行判断。
接下来,代码获取了要检测的构造函数的原型对象,即 right.prototype
,并获取了要检测的对象的原型对象,即 left.__proto__
。然后通过一个 while 循环不断向上查找对象的原型链,直到找到对象的原型链的顶端(即 left === null)或者找到了与构造函数的原型对象相等的对象(即 prototype === left)。
接下来,代码获取了要检测的构造函数的原型对象,即 right.prototype
,并获取了要检测的对象的原型对象,即 left.__proto__
。然后通过一个 while 循环不断向上查找对象的原型链,直到找到对象的原型链的顶端(即 left === null)或者找到了与构造函数的原型对象相等的对象(即 prototype === left)。
如果找到了与构造函数的原型对象相等的对象,则说明该对象是该构造函数的实例,返回 true;否则,说明该对象不是该构造函数的实例,返回 false。
4. 测试:让myInstanceOf
接受严格的洗礼 🚿
我们来进行一些测试,看看我们的 myInstanceOf
是否能够顺利通过。
// 示例构造函数和实例对象
function Person() {}
const person = new Person();
// 正确使用示例
console.log(myInstanceOf(person, Person)); // 输出:true
console.log(myInstanceOf(person, Object)); // 输出:true
console.log(myInstanceOf(person, Array)); // 输出:false
// 非对象类型示例
console.log(myInstanceOf(42, Number)); // 输出:false
console.log(myInstanceOf('Hello', String)); // 输出:false
// 测试继承关系
class Animal {}
class Dog extends Animal {}
const dog = new Dog();
console.log(myInstanceOf(dog, Animal)); // 输出:true
console.log(myInstanceOf(dog, Dog)); // 输出:true
console.log(myInstanceOf(dog, Object)); // 输出:true
看来我们的myInstanceOf
表现得相当不错!我们继续往下探索。
5. 应用场景:instanceof
的真实用武之地 🌱
instanceof
的一个典型应用场景就是类型检查。当我们需要确保一个对象是某个构造函数的实例时,就可以使用instanceof
进行判断。例如,在处理错误时,我们可能需要根据不同类型的错误进行不同的处理:
try {
// Some code that might throw an error
} catch (error) {
if (error instanceof TypeError) {
// Handle TypeError
} else if (error instanceof ReferenceError) {
// Handle ReferenceError
} else {
// Handle other types of errors
}
}
当然了,instanceof
并非完美无缺。因为它依赖于原型链,所以在某些情况下,比如跨 iframe 时,它可能会失效。但在大部分情况下,instanceof
都是一个非常实用的工具,能够帮助我们在 JavaScript 的世界里找到对象与构造函数之间的联系。
结语:一段关于instanceof
的奇幻旅程的终点 🏁
经过一番波折,我们终于完成了这次关于instanceof
的奇幻之旅。我们了解了instanceof
的概念、原理,手写了一个实现,并进行了测试,最后还探讨了它的应用场景。希望你在这趟旅程中收获颇丰!
当然,instanceof
只是 JavaScript 浩瀚宇宙中的一颗星辰,还有许多奇妙的知识等待着我们去探索。让我们共同期待下一次的奇幻之旅!
“探索就是发现的过程,而发现就是对未知事物的理解。” —— 卡尔·萨根
祝大家变得更强!🚀
转载自:https://juejin.cn/post/7239631010429960248