数据类型
- 在ES5的时候,我们知晓的数据类型有6种:
Number、String、Boolean、undefined、object、Null。 - ES6 中新增了一种
Symbol。这种类型的对象永不相等,即使创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。 - 谷歌67版本中还出现了一种
bigInt。是指安全存储、操作大整数。
按照数据存储方式分为基本数据类型(原始类型)和引用数据类型(对象类型)可查看:
- 内存空间又被分为两种,栈内存与堆内存。
-
JavaScript中的原始类型的值被直接存储在栈中,在变量定义时,栈就为其分配好了内存空间,由于栈中的内存空间的大小是固定的,那么注定了存储在栈中的变量就是不可变的。 - 相对于上面具有不可变性的原始类型,我习惯把对象称为引用类型,引用类型的值实际存储在堆内存中,它在栈中只存储了一个固定长度的地址,这个地址指向堆内存中的值。
基本数据类型: String、Number、Boolean、Null、Undefined、Symbol
引用数据类型: Object【Object是个大类,function函数、array数组、date日期...JavaScript的内置函数等都归属于Object】
typeof
typeof 可以用于判断一个变量的类型,我们可以使用 typeof 来判断number, string, object, boolean, function, undefined, symbol 这七种数据类型,可以使用typeof用于判断基本类型,点击查看MDN文档。
但是
object类型不能具体细分其包含的数据类型(对象,数组,Set类型,Map类型),并且Null类型也会被判断为"object"。
instanceof
instanceof 主要的作用就是判断一个实例是否属于某种类型,instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。参考文章。
function Foo() {
}
Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true
原型链:
Object.prototype.toString.call( )
还有一个不错的判断类型的方法,就是Object.prototype.toString,我们可以利用这个方法来对一个变量的类型来进行比较准确的判断。
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
封装函数
为了更方便的使用,我们封装一个函数:
function getType(value) {
let type = typeof value;
if (type !== 'object') { // 如果是原始数据类型,直接返回
return type;
}
// 如果是引用数据类型,再进一步判断,正则返回结果
return Object.prototype.toString.call(value).replace(/^\[object (\S+)\]$/, '$1');
}
getType(123); // number
getType('xxx'); // string
getType(() => {}); // function
getType([]); // Array
getType({}); // Object
getType(null); // Null
总结
简单来说,我们使用 typeof 来判断基本数据类型是没问题的,需要注意的是当用 typeof 来判断 null 类型为object的问题。如果想要判断一个对象的具体类型可以考虑用 instanceof,但是 instanceof 也可能判断不准确,比如一个数组(可以用 Array.isArray(value) 用来判断数组),他可以被 instanceof 判断为 Object。所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call 方法。