js几种数据类型的判断方法

前言

在处理数据时,数据类型的判断是经常用到的逻辑,但是判断方法有很多,选哪个方法呐?要就要看自己的业务场景了,下边来简单说下各种方法和他们的不同之处。

我这里在列举这几种判断方法的同时,主要是按照自己的理解来解释下原理,为什么他们的判断结果是这样子,所以有点啰嗦~见谅
发现我的理解有偏差的地方,请大家帮忙指出~谢谢~

1、typeof方法

说到类型判断第一个进入脑海的方法大概就是typeof了

  • 调用格式

typeof 123 //'number'
typeof '123' //'string'
typeof (6==7) //'boolean'
typeof undefined //'undefined'
typeof Symbol('1') //'symbol'
typeof []  //'object'
typeof {}  //'object'
typeof null //'object'
  • 判断特点:

通过前边的调用结果我们也发现,typeof只能判断简单数据类型以及symbol和undefined的具体数据类型;
Array、Object和null的判断结果都是'object'。
这是为什么呐?

  • 判断分析:

    js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息:

    • 000:对象(包括所有的可以被实例化对象,Array类型的数据也在其中)
    • 010:浮点数
    • 100:字符串
    • 110:布尔
    • 1:整数

    undefined和null有点特殊:
    undefined:用 −2^30 整数来表示;
    null:所有机器码均为0

typeof就是根据低位的1-3位来判断类型的,能够准确区分出number、string和boolean类型。
对象类型低位全是000,没法去区分是什么对象类型,而且还有一个大的误区,null的所有机器码都是0,当然也包括低3位,所以也被认为是object类型。
这样也就解释了我们上边每个类型的判断结果了。

  • 使用注意

本着存在即合理的理念,我们也不能说typeof判断方法是不好的,当我们了解了他的判断结果后,可以选择性的去使用。
一般用来判断当前变量是不是赋值或有没有创建。

2、instanceof方法

从字面上来看,这方法是通过判断目标数据是不是对应的构造函数的实例,来判断数据类型

  • 调用格式

'' instanceof String // false
123 instanceof Number // false
true instanceof Boolean // false
Symbol(1) instanceof Symbol // false
[] instanceof Array //true
({}) instanceof Object //true

undefined和null在判断的时候会报错,因为null和undefined都没有对应的构造函数。

  • 判断分析

其实这方法是判断当前数据是不是对应构造函数的实例,如果是的话,就属于构造函数对应的类型。
so:
1. 字面量创建的字符串、布尔值、数字是简单数据类型,不属于不是构造函数new的实例对象。所以无法通过instanceof判断类型;

String的实例字符串对象

2、Symbol不是一个构造函数,没办法去new一个实例,所以它也无法通过instanceof判断;
3、而数组和对象是符合条件的,他们是对象类型,同时也可以通过Array和Object去new出来一个实例对象。可以通过这个方法判断数据类型。
4、undefined和null作为特殊数据类型,他们的所属类是NullUndefined,但是浏览器把这两个类保护起来了,不允许我们在外面访问使用。去用这个方法判断的时候,会直接报错。大家可以试一下,我这里就不写报错过程了

  • 使用注意

这个方法可以用来区分对象类型的具体类型,但是没法判断其他类型的数据,使用场景比较小。

3、constructor方法

constructor字面上的意思就是通过判断当前数据的构造函数来判断数据类型

  • 调用

'123'.constructor == String //true
(123).constructor == Number //true
true.constructor == Boolean //true
[].constructor == Array //true
({}).constructor == Object //true
Symbol(1).constructor === Symbol //true
  • 判断分析

通过上边的调用很明显就是判断当前数据的constructor属性的指向。如果当前数据的构造函数和制定的构造函数相等,就判断其为对应的类型。

我画了一个简单的原型链示意图:

原型图

上图中Person是构造函数,person1是它的实例对象,实例对象本身是没有constructor属性的,但是根据原型链的继承原理,我们会继续到它的__proto__(原型)上去找,在原型上有个 constructor属性,指向了构造函数Person。

而我们这个方法基本上也是这个原理:
1、作为简单数据类型的'123'、123和true,它们本身不是构造函数的实例,但是他们身上有__proto__属性分别指向了String、Number、Boolaen的原型对象。而这个原型下边的constructor属性指向了对应的构造函数。


2、Symbol本身不是构造函数,但是通过Symbol(1)创建的Symbol类型的值却有一个'constructor'属性指向了Symbol函数,所以他也可以通过这个方法判断数据类型。

3、 关于undefined和null这两个大冤种,大家看下边的截图就明白了:
大冤种的无奈

  • 使用注意

通过上边的介绍我们发现了,constructor方法是除了undefined和null之外,其他常见数据类型都能判断,到现在我们发现这些方法都有自己的缺陷,不仅感叹:“世间安有双全法,不负如来不负卿”。
但是接下来这个方法就是我们期盼已久的全能型选手了~

4、Object.prototype.toString.call()

直接上调用方法示例:

Object.prototype.toString.call('123')
==>'[object String]'
Object.prototype.toString.call(123)
==>'[object Number]'
Object.prototype.toString.call([123])
==>'[object Array]'
Object.prototype.toString.call(true)
==>'[object Boolean]'
Object.prototype.toString.call({a:123})
==>'[object Object]'
Object.prototype.toString.call(Symbol(1))
==>'[object Symbol]'
Object.prototype.toString.call(null)
==>'[object Null]'
Object.prototype.toString.call(undefined)
==>'[object Undefined]'
  • 判断分析

通过以上的示例大家也发现了这个方法可以判断所有类型,其实是因为js中有句话:万物皆对象,Object中有toString方法,所有对象最后原型链的尽头都是Object的原型。
通过call()来改变了方法的this指向,this指向了我们需要判断的数据,也就返回了各自对应的type。

你可能感兴趣的:(js几种数据类型的判断方法)