函数判断变量的数据类型

167 阅读4分钟

要检测的数据类型有 基本数据类型:Number、String、Boolean、Null、undefined 引用数据类型:Function、Array、Object、Error、JSON、RegExp(正则)

以下为创建的检测数据

函数
function fun (name,age,na,li) {
	console.log(this)
}
数组
var arr = [1,2,3]
对象
var obj = {
 	name: 'dpn'
}
字符串
var str = 'dpn'
数字
var num = 18
null
var nul = null
布尔
var flag = true
undefined
var unde
Date
var date = new Date();
JSON
var json = {name:'wenzi', age:25};
正则
var reg  = /^[a-zA-Z]{5,20}$/;
Error
var error= new Error();

1、用typeof检测

       console.log(typeof(fun))//function
       console.log(typeof(arr))//object
       console.log(typeof(obj))//object
       console.log(typeof(str))//string
       console.log(typeof(num))//number
       console.log(typeof(nul))//object
       console.log(typeof(flag))//boolean
       console.log(typeof(unde))//undefined
       console.log(typeof(date))//object
       console.log(typeof(json))//object
       console.log(typeof(reg))//object
       console.log(typeof(error))//object

只有number、string、boolean、function、undefined、object六种数据可以检测出来,其余的都是Objet

一般用来检测基本数据类型,null 会被检测为 object 是因为在浏览器底层记录数据类型的时候,null 的机器码和 object是一样的(000),所以检测 null 的时候会被当作 object 返回

2、用 instanceof 检测

   console.log(str instanceof String)//false
   console.log(num instanceof Number)//false
   console.log(flag instanceof Boolean)//false
   console.log(nul instanceof Object)//false
   console.log(unde instanceof Object)//false
   console.log(arr instanceof Array)//true
   console.log(fun instanceof Function)//true
   console.log(obj instanceof Object)//true
   console.log(date instanceof Date)//true
   console.log(json instanceof Object)//true
   console.log(reg instanceof RegExp)//true
   console.log(error instanceof Error)//true

number、string、boolea、null、undefined都是false

并且null、undefined是在检测Objec类型报false,因为他们两个没有全局类型

一般用来检测引用数据类型

原理:检测当前实例的原型链上是否存在我们要检测的数据类型

	var str = new String('dpn')
	var num = new Number(18)
	var flag = new Boolean(true)

	console.log(str instanceof String)//true
    console.log(num instanceof Number)//true
    console.log(flag instanceof Boolean)//true

number、string、boolean在使用创建构造函数的方式来创建变量时,检测结果是true

3、用constructor检测

在实例对象中有一个属性__proto__是指向原型对象(prototype)在原型对象中有一个属性constructor是指向的构造函数的

因为原型链是一层一层找的,所以实例对象可以直接找constructor 这个构造函数就是数据类型了

不是用new构造函数创建的变量也一样可以通过原型对象指向构造函数的

   console.log(num.constructor == Number)//true
   console.log(str.constructor == String)//true
   console.log(flag.constructor == Boolean)//true
   //console.log(nul.constructor== Object)
   //console.log(unde.constructor== Object)
   console.log(obj.constructor == Object)//true
   console.log(arr.constructor == Array)//true
   console.log(fun.constructor == Function)//true
   console.log(json.constructor == Object)//true
   console.log(date.constructor == Date)//true
   console.log(reg.constructor == RegExp)//true
   console.log(error.constructor == Error)//true

null和undefined没有构造函数

一般用来检测基本数据类型和引用数据类型 直接检测实例的构造函数来进行判断,一般会使用 == 的方式进行判断

4、使用Object.prototype.toString.call

 console.log(Object.prototype.toString.call(num))//[object Number]
 console.log(Object.prototype.toString.call(str))//[object String]
 console.log(Object.prototype.toString.call(flag))//[object Boolean]
 console.log(Object.prototype.toString.call(nul))//[object Null]
 console.log(Object.prototype.toString.call(unde))//[object Undefined]
 console.log(Object.prototype.toString.call(obj))//[object Object]
 console.log(Object.prototype.toString.call(arr))//[object Array]
 console.log(Object.prototype.toString.call(fun))//[object Function]
 console.log(Object.prototype.toString.call(json))//[object Object]
 console.log(Object.prototype.toString.call(date))//[object Date]
 console.log(Object.prototype.toString.call(reg))//[object RegExp]
 console.log(Object.prototype.toString.call(error))//[object Error]

打印结果为一个字符串,字符串里是一个数组,数组的第二个元素就是我们要的数据类型

都可以检测出来

如果要封装一个getType函数可以使用这种方法

function getType (data) {
	return Object.prototype.toString.call(data).slice(8,-1)
}

通常用来检测基本数据类型和引用数据类型

原理:

首先

1、像Array、Function等数据类型都会继承Object原型上的方法,那么toString也会继承,但是他们会在原型上重写这个toString方法,那么该数据类型的实例进行继承toString方法的时候就会执行就近原则,那么就执行了该数据类型函数上重写的toString方法 【一般都是数据转换为String类型的作用,而不是我们想要的获取数据类型的作用】

2、所以如果我们要得出结果就要直接在Object.prototype上直接调用toString方法,在调用的时候使用call或者apply的方式可以让this指向该实例,那么这个实例就可以成功调用Object.prototype上面的toString方法

​第二步要搞懂的就是Object.prototype上面的toString方法是怎么实现获取数据类型的呢?

ES5之前 [[class]]: 【原生对象和宿主对象】

其实,当实例在调用这个方法的时候会作一下三步:

①、把该变量先【装箱】成一个对象,【null和undefined除外,他们可以直接返回】所有的对象都拥一个内部属性 [[Class]] (一个字符串值,表明了该对象的类型),

②、获取this对象的[[Class]]属性的值

③、然后拼接在 [object, 数据类型] 数据类型的位置,我们最终所获取到的也就是这样一个数组格式的字符串

ES6中 [[NativeBrand]]【原生对象】

[[class]]内部属性,没有了,取而代之的是[[NativeBrand]]

[[NativeBrand]]: 该属性的值对应一个标志值(tag value),可以用来区分原生对象的类型 通过上述的方式进行返回一个字符串

返回的结果我们可以通过 slice(8,-1) 的方式进行获取到我们想要的数据类型