JS中数据类型检测的四种方式:
- tyepof [value] :检测数据类型的运算符
- [example] instanceof [class]:检测某一个实例是否属于这个类
- [example].constructor===[class]:检测实例和类关系的,从而检测数据类型
- Object.prototype.toString.call([value]):检测数据类型
一、typeof 判断基本数据类型
功能: 用来检测数据类型的运算符
举例:
1 | typeof 1 // "number" |
但对于引用数据类型,除了函数之外,都会显示”object”:1
2
3typeof [] // "object"
typeof {} // "object"
typeof console.log // "function"
原理:不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息:
000: Object对象类型
010: 浮点数
100:字符串
110:布尔
1:整数
所以typeof null 为”object”, 就是因为在Javascript中二进制前(低)三位都为0的话会被判断为Object类型,而null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回”object”
缺点:
- NaN / Infinity 都是数字类型的,检测结果都是 “number”
- typeof null 的结果是”object”
- typeof 普通对象/数组对象/正则对象, 结果都是”object”
二、instanceof 判断类型
功能:用来判断某个构造函数的 prototype 属性所指向的对象是否存在于要检测的实例的原型链上
,简单说就是判断当前类的原型是否出现在实例的原型链上,注意,instanceof运算符只能用于对象,不适用原始类型的值
举例:
1 | let arr = [10, 20]; |
原理:原理就是js的原型继承机制:
- 每个构造函数都有一个[prototype]属性,这个属性是一个指针,指向一个对象,即:Object.prototype
- 每个实例对象(object )都有一个私有属性 proto,指向它的原型对象的prototype
小tip:
js 获取原型的四种方式:
1 | Object.getPrototypeOf(obj) // 官方推荐 |
1 | var obj = {} |
输出打印结果如下,所以 obj instanceof Object 是true
原型链图解如下:
缺点:
- 要求检测的实例必须是对象数据类型的
- 基本数据类型的实例是无法基于它检测出来的
构造函数创建的就可以检测
字面量方式创建的不能检测 - 数组/对象/正则对象,都是 Object 的实例,检测结果都是 TRUE ,所以无法基于这个结果判断是否为普通对象
三、constructor
功能:判断当前的实例的 constructor的属性值是不是预估的类
举例:1
2
3
4
5
6
7let arr = [],
obj = {},
num = 10;
console.log(arr.constructor === Array); //=>true
console.log(arr.constructor === Object); //=>false
console.log(obj.constructor === Object); //=>true
console.log(num.constructor === Number); //=>true
原理:实例.constructor 一般都等于类.prototype.constructor 也就是当前类本身
缺点:
非常容易被修改,因为JS 中的 constructor 是不被保护的(用户可以自己随便改)
四、Object.prototype.toString.call()
功能:找到 Object.prototype 上的 toString 方法,让 toString 方法执行,并且基于 call 让方法中的 this 指向检测的数据值,这样就可以实现数据类型检测了
原理:
- Object.prototype 用来返回当前实例所属类的信息;
- 每一种数据类型的构造函数的原型上都有toString 方法;
举例:
1 | Object.prototype.toString.call() // 输出"[object Undefined]" |
缺点:
只能检测内置类,不能检测自定义类(因为只要是自定义类返回的都是‘[Object Object]’)
比如自定义一个时间类:
1 | class TimeClass { |