likes
comments
collection
share

前端面试系列-JS篇--一场探寻 instanceof 奥秘的奇幻之旅 🌈

作者站长头像
站长
· 阅读数 29

大家好,我是你们的博客导游!今天,我们要一起踏上一场关于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
评论
请登录