方法一:typeof
- 语法:typeof[val]
- 返回结果:字符串,该字符串中包含所属的数据类型
- 局限性: 基于typeof检测null的结果是’object’,但是null是空对象指针属于基本数据类型,并不是对象(因为所有值在计算机中都以二进制编码存储,浏览器会把前三位是000的当作对象,而null前三位就是000,所以检测的时候浏览器会把null当作对象);基于typeof无法细分出是普通对象还是数组正则等,只要是对象返回的都是‘object’;
- 有个小知识点需要注意下:多个typeof检测的结果一定时字符串’string’(面试题)
typeof typeof typeof {name:'sss'}
方法二:instanceof
- 实例 instanceof 类
- 返回结果:true 或者 false
- 检测机制:验证当前类的原型prototype是否会出现在实例的原型链上,只要在它的原型链上,结果都为true
- 局限性:要检测的实例必须是对象数据类型,基本数据类型无法检测;不管是数组还是正则都是Object的实例,检测结果都是true,所以要想判断是否为普通对象,必须检测好几次才可以;
- 补充:实例时对象数据类的,但是基本值也是对应类的实例,比如10是Number的实例,但是10却不是对象数据类型,个人认为把10理解为不标准的实例( 各位老铁有更好的理解评论区走一波)。
[1,2] instanceof Array
{name:'sss'} instanceof Object
方法三:constructor
- 语法:[val].constructor === 类
- 返回结果:true 或者 false
- 判断当前实例的constructor的属性值是否是你预估的类
- 局限性:把类的原型j进行重定向,在重写过程中可能出现把之前的constructor属性值覆盖掉或者压根没有constructor,这样检测的结果就不准了(注意内置类不能进行重定向,但是内置类的constructor属性值却可以修改);如果给检测的对象数据类型增加私有的constructor属性,检测的结果也就不准确了
Array.prototype.constructor = 'sss';
[].constructor === Array;
方法四:Object.prototype.toString.call()
- 语法:Object.prototype.toString.call([val])
- 目前来说检测结果比较准确,项目中用的也是最多的
Object.prototype.toString.call([])
Object.prototype.toString.call(10)
自己写的数据类型检测方法
function toType(val) {
if (val == null) {
return val + '';
};
let obj = {},
testMethod = obj.toString;
"Boolean Number String Function Array Date RegExp Object".split(' ').forEach(item => {
obj[`[object ${item}]`] = item.toLowerCase();
});
if (typeof val === 'object' || typeof val === 'function') {
return obj[testMethod.call(val)];
}
return typeof val;
};
console.log(toType(1));
console.log(toType(NaN));
console.log(toType([]));
console.log(toType(/^\d+$/));
console.log(toType({}));
console.log(toType(Symbol(1)));