数据类型的几种判断方法以及原理

基本数据类型有
number string undefined null symbol(es6新增) object(function array object) bigInt(es10新增)等 8种

一、 typeof

typeof 目前能返回string,number,boolean,symbol,bigInt,undefined,object,function这八种判断类型
无法判断数组和null
用typeof判断数组和null都会返回object

null既然属于基本数据类型,为什么用typeof返回的是object呢?解答如下:
js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息?

编码类型
000对象
010浮点数
100字符串
110布尔
1整数

但是对于 undefined 和 null 来说,这两个值的信息存储是有点特殊的。
null:所有机器码均为0
undefined:用 −2^30 整数来表示
所以,typeof 在判断 null 的时候就出现问题了,由于 null 的所有机器码均为0,因此直接被当做了对象来看待。

二、 instanceof

instanceof 判断一个实例是否属于某个类的实例
返回一个布尔值

let a  = ()=>{return 1}
a instanceof Array  =>  false

instanceof 就是判断右边变量的prototype 是否在左边的原型链(__ proto __)上

其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。

三、 constructor

当一个函数F被定义时,JS引擎会为F添加prototype原型,然后再在prototype上添加一个constructor属性,并让其指向F的引用。如下所示:

当执行 var f = new F() 时,F被当成了构造函数,f是F的实例对象,此时F原型上的constructor传递到了f上,因此f.constructor == F

可以看出,JS在函数F的原型上定义了constructor,当F被当作构造函数用来创建对象时,创建的新对象就被标记为了“F” 类型,使得新对象有名有姓,可以追溯。

同理,JS中的数据类型也遵守这个规则:

细节问题:
1.null和undefined是无效的对象,因此是不会有constructor存在的,这两种类型的数据可以通过第四种方法来判断。
2.JS对象的constructor是不稳定的,这个主要体现在自定义对象上,当开发者重写prototype后,原有的constructor会丢失,constructor会默认为Object

四、 Object.prototype.toString(这个是判断类型最准的方法)

toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,更严格的讲,是 toString运行时this指向的对象类型, 返回的类型格式为[object,xxx],xxx是具体的数据类型,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,… 基本上所有对象的类型都可以通过这个方法获取到。

Object.prototype.toString.call('') ;         [object String]

Object.prototype.toString.call(1) ;          [object Number]

Object.prototype.toString.call(true) ;       [object Boolean]

Object.prototype.toString.call(undefined) ;  [object Undefined]

Object.prototype.toString.call(null) ;       [object Null]

Object.prototype.toString.call(new Function()) ;  [object Function]

Object.prototype.toString.call(new Date()) ; [object Date]

Object.prototype.toString.call([]) ;         [object Array]

Object.prototype.toString.call(new RegExp()) ; [object RegExp]

Object.prototype.toString.call(new Error()) ;  [object Error]

Object.prototype.toString.call(document) ;   [object HTMLDocument]

Object.prototype.toString.call(window) ;[object global] 
// window是全局对象global的引用

需要注意的是,必须通过Object.prototype.toString.call来获取,而不能直接 new Date().toString(), 从原型链的角度讲,所有对象的原型链最终都指向了Object, 按照JS变量查找规则,其他对象应该也可以直接访问到Object的toString方法,而事实上,大部分的对象都实现了自身的toString方法,这样就可能会导致Object的toString被终止查找,因此要用call来强制执行Object的toString方法。

原文链接:https://blog.csdn.net/xiaolinlife/article/details/90518849

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值