判断数据类型的几种方法

  • 关于数据类型的几种方法

JS中数据类型检测的四种方式:

  • tyepof [value] :检测数据类型的运算符
  • [example] instanceof [class]:检测某一个实例是否属于这个类
  • [example].constructor===[class]:检测实例和类关系的,从而检测数据类型
  • Object.prototype.toString.call([value]):检测数据类型

一、typeof 判断基本数据类型

功能: 用来检测数据类型的运算符

举例:

1
2
3
4
5
6
typeof 1 // "number"
typeof '1' // "string"
typeof undefined // "undefined"
typeof true // "boolean"
typeof null // "object"
typeof Symbol() // "symbol"

但对于引用数据类型,除了函数之外,都会显示”object”:

1
2
3
typeof [] // "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
2
3
4
5
6
let arr = [10, 20];

console.log(typeof arr); //=>"object"
console.log(arr instanceof Array); //=>true
console.log(arr instanceof RegExp); //=>false
console.log(arr instanceof Object); //=>true

原理:原理就是js的原型继承机制:

  • 每个构造函数都有一个[prototype]属性,这个属性是一个指针,指向一个对象,即:Object.prototype
  • 每个实例对象(object )都有一个私有属性 proto,指向它的原型对象的prototype

小tip:

js 获取原型的四种方式:

1
2
3
4
Object.getPrototypeOf(obj) // 官方推荐
obj.__proto__ // 不标准写法
obj.constructor.__proto__ // 间接方式获取
obj.prototype // 不标准写法
1
2
3
4
var obj = {}

console.log(obj._proto_) // 原型对象的prototype
console.log(Object.prototype) // 查看一个构造函数的原型对象

输出打印结果如下,所以 obj instanceof Object 是true

原型链图解如下:

缺点:

  • 要求检测的实例必须是对象数据类型的
  • 基本数据类型的实例是无法基于它检测出来的
    构造函数创建的就可以检测
    字面量方式创建的不能检测
  • 数组/对象/正则对象,都是 Object 的实例,检测结果都是 TRUE ,所以无法基于这个结果判断是否为普通对象

三、constructor

功能:判断当前的实例的 constructor的属性值是不是预估的类

举例:

1
2
3
4
5
6
7
let 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
2
3
4
5
6
Object.prototype.toString.call() // 输出"[object Undefined]"
Object.prototype.toString.call(1) // 输出"[object Number]"
Object.prototype.toString.call('') // 输出"[object String]"
Object.prototype.toString.call({}) // 输出"[object Object]"
Object.prototype.toString.call(new Date()) // 输出"[object Date]"
Object.prototype.toString.call(/a/) // 输出"[object RegExp]"

缺点:
只能检测内置类,不能检测自定义类(因为只要是自定义类返回的都是‘[Object Object]’)

比如自定义一个时间类:

1
2
3
4
5
6
7
8
9
10
class TimeClass {
constructor (date) {
if (!date || typeof (date) === 'string') {
date = new Date()
}
this.date = date
}
}
let a = new TimeClass()
console.log(Object.prototype.toString.call(a)) // 输出 "[object Object]"

Comentarios

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×