在js中,我们通常将数据内存中的存储方式不同。 将他们分为2种数据类型.
简单数据类型(基本数据类型)
- Number:数字
- String:字符串
- Boolean:布尔
- Null:表示缺少对象(一般用来指完全为空的对象)
- Undefined:申明了变量但是未赋值
- Symbol:独一无二的值(ES6新增,解决命名冲突的问题)
- BigInt:任意大的整数(没有2^53-1范围限制) 基本数据类型是直接存储在栈中的简单数据段,占据空间小,属于被频繁使用的数据。拷贝的时候的时候可以直接拷贝数据
复杂数据类型(引用数据类型)
引用数据类型是存储在堆内存中,占据空间大。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体.浅拷贝的话是拷贝内存地址的指针.
- Object:普通对象
- Function/function:构造函数/函数
- Array:数组
- Reg:正则
- Date:时间
- Math:数学
数据类型判断
在日常开发中 我们经常会使用到数据类型的判断,以下几种都是我们常用的几种方法
typeof
- typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。
- typeof判断基础数据类型(不包含bull)没问题,但是判断复杂数据类型的时候会有一些意外的结果,除了function返回function,其他都是返回object.
- typeof的原理是检查数据的二进制,而null的是000开头的和对象是一样的所以null返回的也是object
instanceof
- instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。
- instanceof 不能判断简单数据类型 除非这个数据不是字面量,而是通过new出来的 比如
a = new String('a')
a instanceof String // true
- instanceof判断复杂数据类型的时候,也有一些问题,比如
[] instanceof Array // true
[] instanceof Object // true
复杂数据类型除了他自己的构造函数还可以是Object
constructor
- 通过原型链的constructor可以指回构造函数的原理
- null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断
- 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object
toString
-
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
-
对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
一些特殊的判断
- Array.isArray() 判断参数是否是数据
- isNaN()判断参数是不是非数字
toType
这是一个jQuery封装的判断数据类型的,十分好用,可以写到项目的通用函数里面直接调用
var getProto = Object.getPrototypeOf; //获取实例的原型对象
var class2type = {};
var toString = class2type.toString; //Object.prototype.toString 检测数据类型
var hasOwn = class2type.hasOwnProperty; //Object.prototype.hasOwnProperty
var fnToString = hasOwn.toString; //Function.prototype.toString 把函数转换字符串
var ObjectFunctionString = fnToString.call(Object); //"function Object() { [native code] }"
// 循环数据中的每一项:建立数据类型检测的映射表
// + [object Boolean]/[object Number]/[object String]都是为了处理基于”构造函数“创建的基本数据值的引用类型值,最后期许检测出来的结果依然是"boolean"/"number"/"string"
// typeof new Number(10) -> "object"
// toString.call(new Number(10)) -> "[object Number]"
[
'Boolean',
'Number',
'String',
'Symbol',
'Function',
'Array',
'Date',
'RegExp',
'Object',
'Error',
'GeneratorFunction'
].forEach(function (name) {
class2type['[object ' + name + ']'] = name.toLowerCase();
});
// 检测数据类型的公共方法
function toType(obj) {
// null/undefined
if (obj == null) {
return obj + '';
}
// 如果是引用数据类型(包含:new Number(10)这种),则基于Object.prototype.toString来检测(拿检测的结果到之前建立的映射表中去匹配查找,找到对象的小写数据类型);而基本数据类型,之前排除了null/undefined,剩下的基于typeof即可解决!
return typeof obj === 'object' || typeof obj === 'function'
? class2type[toString.call(obj)] || 'object'
: typeof obj;
}