目录:

1.基本数据类型

2.引用数据类型

3.检测数据类型的方法

1.基本数据类型

• number

• string

• boolean 

• null

• undefined 

• symbol 

这里讨论的不是通过new出来的基本类型,也就是说讨论的不是他们的包装类

因为当用包装类的方式时,用typeof判定都是object

2.引用数据类型

• Object ( Array 、 Date 、 RegExp )

• Function

3.检测数据类型的4种方式

3.1 typeof 讲解

3.1.1typeof的使用

返回值是字符串。例如undefined、object、boolean、symbol

我们先看下面的几个typeof的判断:

typeof null // object
typeof undefined // undefined
typeof 52 // number
typeof  "laochen" // string
typeof true // boolean
typeof Symbol() // symbol
typeof (()=>{}) //function
typeof {}  // object
typeof [] // objcet
typeof /aaaa/ //objcet
typeof new Date() //objcet

总结:typeof 无法判断具体对象类型,如时间,正则,数组,空对象,null 都为objcet

3.1 .2typeof的原理

js是一门弱类型语言,每个变量在存储值之外,还会存储变量的类型,js中使用32位的bit存储变量信息,低位的1-3个bit存储变量类型信息,我们可以叫它为类型标签type tag。

举个例子:

...... xxxxx x000 //最后三位,000为objcet

...... xxxxx x001 //最后一位,为1时则是int

...... xxxxx x010 //倒数第二位则为 double

...... xxxxx x100 //倒数三位,则为string

...... xxxxx x110//倒数第三位和第二位为1,则为boolean

所以,null undefined 和Function 并没有分配type tag

那么,typeof能通过一个对象是否实现了[[call]] 内部方法,如果实现了,则判断为Function,而undfined 变量 存储的是一个特殊的值,typeof会判断这个值,则认为是undefined

null是个特殊的例子,因为存储的低位恰好也是000,跟object是一致的,命中type tag,所以通过typeof是无法判断null的。

如何判断一个对象不是null

比较经典的解法:

可以通过objcet装修的功能

function getObjcet(obj){
 
   
  
    return Objcet(obj) === obj;
 
   
  
}
 
   
  
getObjcet({}) //true
 
   
  
getObject(null) // false

3.2 Objcet.prototype.toString 可以用来判断各种内置对象

3.2.1 Objcet.prototype.toString 解释

如果是一个实参的基本类型,会自动转化成为对应的引用类型。

null和undefined不存在对应的引用类型,会转为内部特殊处理。

3.2.2 Objcet.prototype.toStrting 的原理

每个对象都有一个内部属性 [[Class]],它的值有 'Argunments' 'Array' 'Boolean' 'Date' 'Error' 'Function' 'JSON' 'Math' 'Number' 'Objcet' 'RegExp' 'String' ,并且只能通过Objcet.prototype.toString来访问

3.2.3 Symbol.toStringTag 被访问

其实Objcet.prototype.toString内部会先访问对象的Symbol.toStringTag属性值来拼接返回值。

我们可以验证一下

let aa = 'test'
 
   
  
console.log(Objcet.prototype.toString.call(aa)) // "[object String]"
 
   
  
Objcet.defineProperty(String.prototype,Symbol.toStringTag,{
 
   
  
    get(){
 
   
  
    return 'ibeatyou'
 
   
  
}
 
   
  
})
 
   
  
console.log(Object.prototype.toString.call(test)) // [object ibeatyou]

前后对比,就可以知道,先访问Symbol.toStringTag,返回了 get()的值。

3.2.4 Object.prototype.toString 的使用总结

  • 如果是undefined ,返回[object Undefined]
  • null => [object Null]
  • 如果是基本类型或者是内置对象,则转化为封装类型[object 封装类型]
  • 获取对象的Symbol.toStringTag 属性值subType 如果subType是个字符串,则返回[object subType] 否则,就会获取对象的[[Class]] 属性值 type ,返回[object type]

3.3 instanceof

3.3.1 instanceof的原理及语法

instanceof 操作符判断构造函数constructorFunc的prototype属性是否存在对象object的原型链上。同时我们可以利用Symbol.hasInstance函数自定义intanceof操作逻辑。

Object.create({}) instanceof Object // true
 
   
  
Object.create(null) instanceof Object // false 此方法可以判断数据是否为null的对象
 
   
  
Function instanceof Object // true
 
   
  
Object instanceof Object // true

Symbol.hasInstance自定义instanceof:

let obj = {}
 
   
  
Object.defineProperty(obj,Symbol.hasInstance,{
 
   
  
    value:function(){
 
   
  
        return true;
 
   
  
}
 
   
  
})

52 intanceof obj // true

3.3.2 instanceof的总结

1)instanceof 不会对基本类型做隐式转换。

如:'1111' instanceof String // false

2)constructorFunc必须是一个对象,并且大部分情况下是个构造函数。具有prototype属性。

52 instanceof 52 // 错误不是对象
 
   
  
1 instanceof {} // 错误
 
   
  
({}) instanceof (()=>{}) // Function 没有prototype属性

3)instanceof 的缺陷,因为不同的全局执行上下文的对象和函数都是不相等的,所以对于跨全局执行上下文instanceof 就不能正常工作了。

3.4 内置的类型判断方法

3.4.1 Array.isArray

Es5引入了用于数组类型的判断方法

3.5 内置对象的prototype属性类型判断

基本类型的引用类型.prototype 

  1. 该写法不是该引用类型的实例。
  2. 通过 Object.prototype.toString.call() 可以判断他的类型
// 举例
 
   
  
let num = Number.protype
 
   
  
console.log(num instanceof Number) // false
 
   
  
console.log(Object.prototype.toString.call(num)) // [object Number]