深入浅出:JavaScript中instanceof详解

1.前言

在现实世界中,我们会对物品有个大致分类,比如吃的物品、穿的衣服、用的东西等等,这是我们生活基本需要。在我们生活的世界里,其实最复杂的应该就是我们人类了,对人类的溯源应该可以追溯到远古时代...。所以在现实世界中,其他任何东西对比人类都可以当成是基本分类,人类是复杂分类。在编程世界中(JavaScript语言),对编程的元素也会有基本类型的定义: StringNumberBooleannullundefinedSymbolBigInt;也有复杂分类引用类型:Object。这些类型在编程的逻辑世界中灵活自由组合应用,组成编程的大千世界。

在这里重点说引用类型,它也有自己的一套机制,如果你想了解它,它会根据自己的原型链机制,进行溯源追溯。溯源机制可以想象是人类文明中的家族族谱,属不属于这个家族可以在族谱中查看,甚至属于哪个旁支都可以查找到。

2.详解

  1. 原型链:在 JavaScrit 中每个对象都有一个指向原型对象的指针(__proto__),指针指向构造函数的原型对象,构造函数的原型对象同时也是一个普通的对象,所以也会指向它构造函数的原型对象,这样层层向上查找,直到终点null为止,这样就形成了原型链。

2. JavaScript中 instanceof 方法的原理就是利用了原型链机制,例如f instanceof Father,f 是一个实例对象,Father 是一个构造函数,判断构造函数 Father 的原型对象是否在 f 实例对象的原型链上。若是则返回 true,否则返回 false。

javascript 复制代码
class Father {
    //姓氏
    static familyName = '张';
    constructor(name) {
        this.name = Father.familyName + name;
    }
}

class Son extends Father {
    constructor(name) {
        super()
        this.name = Son.familyName +  name;
    }
}

const f = new Father('一');
console.log(f) // Father { name: '张一' }
const s = new Son('三');
console.log(s) // Son { name: '张三' }
console.log(f instanceof Father); // true
console.log(s instanceof Father); // true
console.log(s instanceof Son); // true
console.log(f instanceof Son); // false

3.适用场景

根据instanceof的原理,它只适用于引用类型,对于用字面量的形式声明的基本类型检测不出来,全部返回 false。因为包装对象是引用类型,例如new Number(1),但是不推荐这种写法。

javascript 复制代码
console.log(1 instanceof Number) //false
console.log('1' instanceof String) //false
console.log(true instanceof Boolean) //false
console.log(null instanceof Object) //false
console.log(undefined instanceof Object) //false
console.log(Symbol.for('a') instanceof Symbol) //false
console.log(10n instanceof BigInt) //false

4.优缺点

  • 优点:instanceof 能够准确检测引用类型的类型
  • 缺点:
    • 基本类型检测不出来
    • 根据它的原理,利用原型链查找,在复杂情况下,性能会又损耗

5.代码实现

5.1 类型判断

我们可以借助 typeof 方法去排除基本类型,我们既要function,又排除 null

  • typeof null === "object"
  • typeof function(){} === "function"
javascript 复制代码
const myInstanceOf = (obj,constructor) => {
    if((typeof obj === null || typeof obj !== "object") && typeof obj !== "function") return false
}

5.2 获取实例对象的原型

我们使用 Reflect.getPrototypeOf(obj) 获取实例对象的原型

javascript 复制代码
const myInstanceOf = (obj,constructor) => {
    if((typeof obj === null || typeof obj !== "object") && typeof obj !== "function") return false

    let prototype = Reflect.getPrototypeOf(obj)
}

5.3 与构造函数的原型对象对比

用循环对比实例对象上原型链的每一个原型对象与构造函数的原型对象,结束条件是原型链的终点是null

javascript 复制代码
const myInstanceOf = (obj,constructor) => {

    if((typeof obj === null || typeof obj !== "object") && typeof obj !== "function") return false

    let prototype = Reflect.getPrototypeOf(obj)

     while(prototype){

        if(prototype === constructor.prototype){
            return true
        }

        prototype = Reflect.getPrototypeOf(prototype)

    }

    //若实例对象原型链上没有找到构造函数的原型对象,则返回 false
    return false
}

5.4 测试验证

javascript 复制代码
console.log(myInstanceOf(1,Number)) //fßalse
console.log(myInstanceOf(NaN,Number)) //false
console.log(myInstanceOf('1',String)) //false
console.log(myInstanceOf(true,Boolean)) //false
console.log(myInstanceOf(null,Object)) //false
console.log(myInstanceOf(undefined,Object)) //false
console.log(myInstanceOf(Symbol.for('a'),Symbol)) //false
console.log(myInstanceOf(10n,BigInt)) //false



console.log(myInstanceOf({},Object)) //true
console.log(myInstanceOf([],Array)) //true
console.log(myInstanceOf(function(){},Function)) //true
console.log(myInstanceOf(new Date(),Date)) //true
console.log(myInstanceOf(new RegExp(''),RegExp)) //true


console.log(myInstanceOf(new Number(1),Number)) // true

6.总结

typeof 方法是用来检测基本类型的类型,instanceof 用来检测引用类型的类型,因为 instanceof的机制是利用原型链进行查找,所以在原型链比较复杂的情况下,那检测性能会受到影响

相关推荐
Hilaku44 分钟前
为什么我坚持用git命令行,而不是GUI工具?
前端·javascript·git
歪歪1001 小时前
Vue原理与高级开发技巧详解
开发语言·前端·javascript·vue.js·前端框架·集成学习
用户2519162427111 小时前
Canvas之画图板
前端·javascript·canvas
EndingCoder2 小时前
Next.js API 路由:构建后端端点
开发语言·前端·javascript·ecmascript·全栈·next.js·api路由
阳火锅3 小时前
# 🛠 被老板逼出来的“表格生成器”:一个前端的自救之路
前端·javascript·面试
Hilaku3 小时前
我给团队做分享:不聊学什么,而是聊可以不学什么
前端·javascript·架构
Juchecar3 小时前
TypeScript 中字符串与数值、日期时间的相互转换
javascript·python
土豆_potato3 小时前
5分钟精通 useMemo
前端·javascript·面试
用户6757049885023 小时前
一文吃透 Promise 与 async/await,异步编程也能如此简单!建议收藏!
前端·javascript·vue.js
姑苏洛言4 小时前
使用 ECharts 实现菜品统计和销量统计
前端·javascript·后端