instanceof 操作符的原理及手写

intsanceof 是什么

instanceof 用于检测一个对象是不是另一个对象的实例。

用法

js 复制代码
obj instanceof Class
  • 如果 obj 隶属于 Class 类(或 Class 类的子类),则返回 true。例如:
js 复制代码
class Rabit {};
let rabit = new Rabit();

// rabit 是 Rabit 类的对象吗?
console.log(rabit instanceof Rabit); // true
  • instanceof 还适用于检测父类。
js 复制代码
class Animal { };
class Rabit extends Animal { };
let rabit = new Rabit();

// rabit 是 Animal 子类的对象吗?
console.log(rabit instanceof Animal); // true
// 判断对象实例的原型对象和类的原型对象是否一致可以确定obj是该类的实例还是父类的实例
console.log(Object.getPrototypeOf(rabit) === Animal.prototype); // false
  • 当然它也适用于构造函数的写法。
js 复制代码
function Animal() { };
function Rabit() { };

let ani = new Animal();
Rabit.prototype = ani; // 原型继承
let rabit = new Rabit();
let animal = new Animal();

console.log(rabit instanceof Rabit); // true
console.log(rabit instanceof Animal); // true
  • instanceof 只能正确判断引用数据类型 ,而不能正确判断基本数据类型
js 复制代码
console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 

console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true

基本数据类型不具备对象的特征,没有原型链可言,所以无法通过 instanceof 判断,应该使用 typeof

实现原理

instanceof 的工作原理就是判断在一个对象原型链中能否找到该类型(构造函数)的原型

它会顺着原型链依次去比较,直到obj.__prototype__ === Class.prototype为止。

ini 复制代码
obj.__proto__ === Class.prototype?
obj.__proto__.__proto__ === Class.prototype?
obj.__proto__.__proto__.__proto__ === Class.prototype?
...
// 如果任意一个的答案为 true,则返回 true
// 否则,如果我们已经检查到了原型链的尾端,则返回 false

像前面提到的 rabit instanceof Animal 这个例子,它会先和自身的原型对象匹配,再一直顺着原型链去和父类的原型对象匹配:

scala 复制代码
class Animal {}
class Rabbit extends Animal {}

let rabbit = new Rabbit();
alert(rabbit instanceof Animal); // true

// rabbit.__proto__ === Animal.prototype(无匹配)
// rabbit.__proto__.__proto__ === Animal.prototype(匹配!)

下图展示了 rabbit instanceof Animal 的执行过程中,Animal.prototype 是如何参与比较的:

手写instanceof

既然我们已经理解了原理,那么就来试试动手实现一个 Instanceof 吧。

js 复制代码
// left传入obj,right传入类
function myInstanceof(left, right) {
    // 遇到基本数据类型直接返回false,有些博客都漏了这一步
    if (typeof left !== 'object' || typeof left !== 'function' || left === null) {
        return false;
    };
    
    // 也可以通过Object.getPrototypeOf(left)拿到原型对象
    let proto = left.__proto__;
    let prototype = right.prototype;

    while (true) {
        // 已经到原型链尽头null
        if (!proto) return false;
        // 匹配,返回true
        if (proto === prototype) return true;
        // 顺着原型链更新指针
        proto = proto.__proto__;
    }
}

测试:

js 复制代码
function myInstanceof(left, right) {
    // 遇到基本数据类型直接返回false,有些博客都漏了这一步
    if (typeof left !== 'object' || typeof left !== 'function' || left === null) {
        return false;
    };
    
    // 也可以通过Object.getPrototypeOf(left)拿到原型对象
    let proto = left.__proto__;
    let prototype = right.prototype;

    while (true) {
        // 已经到原型链尽头null
        if (!proto) return false;
        // 匹配,返回true
        if (proto === prototype) return true;
        // 顺着原型链更新指针
        proto = proto.__proto__;
    }
}

console.log(myInstanceof(function () {}, Function)); // true
console.log(myInstanceof({}, Object)); // true
console.log(myInstanceof([], Function)); // false
console.log(myInstanceof(1, Number)); // false

如有问题欢迎在评论区讨论,一起进步!

相关推荐
vvilkim3 小时前
深入理解 TypeScript 中的 implements 和 extends:区别与应用场景
前端·javascript·typescript
GISer_Jing3 小时前
前端算法实战:大小堆原理与应用详解(React中优先队列实现|求前K个最大数/高频元素)
前端·算法·react.js
振鹏Dong4 小时前
超大规模数据场景(思路)——面试高频算法题目
算法·面试
uhakadotcom4 小时前
Python 与 ClickHouse Connect 集成:基础知识和实践
算法·面试·github
uhakadotcom4 小时前
Python 量化计算入门:基础库和实用案例
后端·算法·面试
写代码的小王吧4 小时前
【安全】Web渗透测试(全流程)_渗透测试学习流程图
linux·前端·网络·学习·安全·网络安全·ssh
uhakadotcom5 小时前
使用Python获取Google Trends数据:2025年详细指南
后端·面试·github
uhakadotcom5 小时前
使用 Python 与 Google Cloud Bigtable 进行交互
后端·面试·github
uhakadotcom5 小时前
使用 Python 与 BigQuery 进行交互:基础知识与实践
算法·面试
uhakadotcom5 小时前
使用 Hadoop MapReduce 和 Bigtable 进行单词统计
算法·面试·github