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

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

相关推荐
cellurw4 小时前
20260724 六组件编译收尾与全局构建验证
前端
寒水馨4 小时前
Windows下载、安装electron-v43.2.0(附安装包electron-v43.2.0-win32-x64.zip)
javascript·windows·typescript·electron·跨平台·桌面应用·chromium
用户2930750976694 小时前
用React 完成Todos 的 组件应用:深入理解单向数据流与组件通信
前端
玉宇夕落4 小时前
React 父子组件通信 Todo List 看透单向数据流与不可变数据
前端
软件开发技术深度爱好者4 小时前
国际音标魔法实验室工具HTML5实现
前端·html5·英语学习
FogLetter4 小时前
嘘!WebSocket正在“偷听”你的网络请求——全双工通信的魔法
前端·面试
用户938515635074 小时前
从零构建 React Todo 应用:组件化设计与数据流深度解析
前端·javascript
IT_陈寒4 小时前
Python线程池把我坑惨了,这些盲区你不踩?
前端·人工智能·后端
mONESY4 小时前
从 DeepSeek WebGPU 输入框,吃透 React+TS 四大核心开发实践
javascript·后端
程序员爱钓鱼4 小时前
Rust HashMap 详解:键值存储、查询、更新与统计
后端·面试·rust