JavaScript的数据类型判断
原始数据类型
原始数据类型有:Undefined、Null、Boolean、Number、String、Symbol 、 Bigint。
其中 Symbol 和 BigInt 是ES6 中新增的数据类型:
- Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。
- BigInt 是一种数字类型的数据,提供了一种方法来表示大于2^53-1的整数。BigInt可以表示任意大的整数,Number类型只能安全的支持-2^53-1 和 2^53-1之间的整数,任何超过这个范围的数值都会失去精度;而BigInt可以解决这个问题
原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
null和undefined区别
undefined
代表的含义是未定义,一般变量声明了但还没有定义的时候会返回 undefined
null
代表的含义是空对象,null主要用于赋值给一些可能会返回对象的变量,作为初始化。
null
是一个表示“空”的对象,转为数值时为0
;undefined
是一个表示"此处无定义"的原始值,转为数值时为NaN
。
引用数据类型
引用数据类型为Object,通常在JS中表现为对象、数组和函数
引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
判断数据类型
JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof运算符
console.log(typeof 2); // number console.log(typeof true); // boolean console.log(typeof 'str'); // string console.log(typeof []); // object console.log(typeof function(){}); // function console.log(typeof {}); // object console.log(typeof undefined); // undefined console.log(typeof null); // object
注意:
- 数组、对象、null都会被判断为object,其中null为object是历史原因造成的,被当左object的特殊值,需要强行记忆。
- 空数组(
[]
)的类型也是object
,这表示在 JavaScript 内部,数组本质上只是一种特殊的对象
instanceof运算符
instanceof
可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型,表示对象是否为某个构造函数的实例
console.log(2 instanceof Number); // false console.log(true instanceof Boolean); // false console.log('str' instanceof String); // false console.log([] instanceof Array); // true console.log(function(){} instanceof Function); // true console.log({} instanceof Object); // true var v = new Vehicle(); v instanceof Vehicle // true
注意:
instanceof
只能正确判断引用数据类型,因为基本数据类型不是一个对象,没有原型链,所以不能判断基本数据类型。instanceof
运算符的左边是实例对象(v),右边是构造函数(Vehicle)。它会检查右边构造函数的原型对象(Vehicle.prototype),是否在左边对象的原型链上(v.__proto__)。由于
instanceof
检查整个原型链,因此同一个实例对象,可能会对多个构造函数都返回true
。var d = new Date(); d instanceof Date // true d instanceof Object // true
上面代码中,
d
同时是Date
和Object
的实例,因此对这两个构造函数都返回true
。
constructor
constructor
有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor
对象访问它的构造函数。
console.log((2).constructor === Number); // true console.log((true).constructor === Boolean); // true console.log(('str').constructor === String); // true console.log(([]).constructor === Array); // true console.log((function() {}).constructor === Function); // true console.log(({}).constructor === Object); // true
注意:
- 如果创建一个对象来改变它的原型,
constructor
就不能用来判断数据类型了,所以不是很安全
Object.prototype.toString方法
实例对象(比如[] function
)可能会自定义toString
方法,覆盖掉Object.prototype.toString
方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString
方法。通过函数的call
方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。
Object.prototype.toString.call(2) // "[object Number]" Object.prototype.toString.call('') // "[object String]" Object.prototype.toString.call(true) // "[object Boolean]" Object.prototype.toString.call(undefined) // "[object Undefined]" Object.prototype.toString.call(null) // "[object Null]" Object.prototype.toString.call(Math) // "[object Math]" Object.prototype.toString.call({}) // "[object Object]" Object.prototype.toString.call([]) // "[object Array]"
不同数据类型的Object.prototype.toString
方法返回值如下。
- 数值:返回
[object Number]
。 - 字符串:返回
[object String]
。 - 布尔值:返回
[object Boolean]
。 - undefined:返回
[object Undefined]
。 - null:返回
[object Null]
。 - 数组:返回
[object Array]
。 - arguments 对象:返回
[object Arguments]
。 - 函数:返回
[object Function]
。 - Error 对象:返回
[object Error]
。 - Date 对象:返回
[object Date]
。 - RegExp 对象:返回
[object RegExp]
。 - 其他对象:返回
[object Object]
。
判断数组
- 通过Object.prototype.toString.call()做判断
Object.prototype.toString.call(obj).slice(8,-1) === 'Array';
- 通过原型链做判断
obj.__proto__ === Array.prototype;
- 通过ES6的Array.isArray()做判断
Array.isArrray(obj);
- 通过instanceof做判断
obj instanceof Array
- 通过Array.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(obj)