Lawguancong / Daily-Charging-Learning

0 stars 0 forks source link

typeof & instanceof区别 #19

Open Lawguancong opened 3 years ago

Lawguancong commented 3 years ago

数据类型

image

typeof

但是对象来说,typeof 不能正确的判断其类型, typeof 一个函数可以输出 'function',而除此之外,输出的全是 object,这种情况下,我们无法准确的知道对象的类型。 instanceof可以准确的判断复杂数据类型,但是不能正确判断基本数据类型。

typeof返回一个表示数据类型的字符串,返回结果包括:

基础类型

• number • string • boolean • undefined • bigint

引用类型

• function • object (object null array map set date reg等等,不能友好序列化)

如何能准确获取数据类型

Object.prototype.toString.call()

// 基础类型
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
Object.prototype.toString.call(BigInt("9007199254740995")) // "[object BigInt]"

// 引用类型: function & object
Object.prototype.toString.call(() => {}) // "[object Function]"

Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(new Set()) // "[object Set]"
Object.prototype.toString.call(new Map()) // "[object Map]"
Object.prototype.toString.call(new Date()) // "[object Date]"
Object.prototype.toString.call(new RegExp()) // "[object RegExp]"

Object.prototype.toString.call 生效原理是什么?

首先了解一个概念:在js中,一切皆对象。一切皆来自一个”根“原型 可以理解成有个“根“原型,创造各类构造函数(包括Object构造函数)。“根“原型类似祖先,在最顶层,在往上就是null “根”原型 === Object.prototype “根”原型(Object.prototype)下,有个toString的方法,记录着所有 数据类型(构造函数) .call作用是改this指向。让传入的对象,执行 “根”原型的toString方法 image

instanceof

instanceof操作符判断左操作数对象的原型链上是否有右边这个构造函数的prototype属性,也就是说指定对象是否是某个构造函数的实例,最后返回布尔值。

instanceof 是通过原型链判断的,A instanceof B, 在A的原型链中层层查找,是否有原型等于B.prototype,如果一直找到A的原型链的顶端(null;即Object.proptotype.proto),仍然不等于B.prototype,那么返回false,否则返回true.

function instance_of(L, R) { // L 表示左表达式,R 表示右表达式
    while (true) {
        if(L === null) { // 已经找到原型链的顶端 即Object.proptotype.proto
            return false;
        } else if(L.__proto__ ===  R.prototype) {
            return true;
        } 
        L = L.__proto__; // 继续向上一层原型链查找
    }
}

总结

简单来说,我们使用 typeof 来判断基本数据类型是 ok 的,不过需要注意当用 typeof 来判断 null 类型时的问题,如果想要判断一个对象的具体类型可以考虑用 instanceof,但是 instanceof 也可能判断不准确,比如一个数组,他可以被 instanceof 判断为 Object。所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call 方法。

参考链接 https://juejin.cn/post/6844903613584654344
https://juejin.cn/post/6991653255847772167 https://github.com/YvetteLau/Blog/blob/master/JS/data-type.js