深入浅出: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的机制是利用原型链进行查找,所以在原型链比较复杂的情况下,那检测性能会受到影响

相关推荐
缘如风5 小时前
easyui 获取自定义的属性
前端·javascript·easyui
诗书画唱5 小时前
【前端教程】JavaScript 实现图片鼠标悬停切换效果与==和=的区别
开发语言·前端·javascript
光影少年5 小时前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划
_r0bin_5 小时前
分片上传-
前端·javascript·状态模式
东北南西5 小时前
手写React状态hook
前端·javascript·react.js
诗书画唱5 小时前
【前端教程】JavaScript DOM 操作实战案例详解
开发语言·前端·javascript
quan26316 小时前
Vue实践篇-02,AI生成代码
前端·javascript·vue.js
小桥风满袖7 小时前
极简三分钟ES6 - 类与继承
前端·javascript
子兮曰7 小时前
🚀99% 的前端把 reduce 用成了「高级 for 循环」—— 这 20 个骚操作让你一次看懂真正的「函数式折叠」
前端·javascript·typescript
wifi歪f7 小时前
📦 qiankun微前端接入实战
前端·javascript·面试