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

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

相关推荐
小小小小宇4 小时前
虚拟列表兼容老DOM操作
前端
悦悦子a啊4 小时前
Python之--基本知识
开发语言·前端·python
安全系统学习5 小时前
系统安全之大模型案例分析
前端·安全·web安全·网络安全·xss
涛哥码咖5 小时前
chrome安装AXURE插件后无效
前端·chrome·axure
OEC小胖胖5 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水5 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐5 小时前
零基础学HTML和CSS:网页设计入门
前端·css
老虎06276 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
三水气象台6 小时前
用户中心Vue3网页开发(1.0版)
javascript·css·vue.js·typescript·前端框架·html·anti-design-vue
灿灿121386 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css