开篇简述
本篇博文将从以问答的方式,带大家详细了解一下js中的数据类型检测
1.js数据类型检测有几种?
- js数据类型检测有四种,分别为
- typeof([value)
- [实例] instanceof [类]
- constructor
- Object.prototype.toString.call([value])
2.这几个方法有什么区别?(这样问其实是想看看你对这些方法的原理熟悉多少)
2.1 typeof
- 用法:typeof [value] 返回结果是一个字符串(字符串中包含了对应的数据类型)
- 特性:使用起来简单,基本数据类型值基本上都可以有效检测,引用数据类型值也可以检测出来 "number"/"string"/"boolean"/"undefined"/"symbol"/"bigint"/"object"/"function"
- 缺陷:对于数组、普通对象、正则等,返回结果都是"object",所以无法基于typeof细分对象数据类型
- 下面给出一些例子供大家参考
console.log(typeof 1);//='number'
console.log(typeof '1');//=>'string'
console.log(typeof false);//=>'boolean'
console.log(typeof null);//=>'object'
console.log(typeof undefined);//=>'undefined'
console.log(typeof []);//=>'object'
console.log(typeof {});//=>'object'
console.log(typeof function(){});//=>'function'
console.log(typeof 9007199254740991n);//=>'bigint'
console.log(typeof Symbol(1));//=>'symbol'
//这里没按需要特别注意的是,连续两个或以上的typeof 返回结果必定是'string
typeof typeof [] === "string"
//因为null是一个空指针,所以typeof检测结果为一个对象
typeof null === "object"
2.2 instanceof
- 用法:[实例] instanceof [类]:用来检测当前实例是否属于这个类。
- instanceof检测机制:验证当前类的原型prototype是否会出现在实例的原型链__proto__上,只要在它的原型链上,则结果都为TRUE
- 特性:基于这种方式,可以弥补typeof无法细分对象类型的缺点(想检测这个值是否为数组,只需要看他是否为Array类的实例即可)
- 缺陷:
- 1)instanceof检测的实例必须都是引用数据类型的,它对基本数据类型值操作无效
- 2)不管是数组对象还是正则对象,都是Object的实例,检测结果都是TRUE,所以无法基于这个结果判断是否为普通对象
- 3)由于instanceof的检测机制造成的,当我们收到你的改变一个函数的原型时,会出现未知的错误
- 下面给出一些例子供大家参考
//==================基础检测
console.log(typeof arr); //=>"object"
console.log(arr instanceof Array); //=>true
console.log(arr instanceof RegExp); //=>false
//=================================缺陷1
console.log(10 instanceof Number); //=>false
console.log(new Number(10) instanceof Number); //=>true
//=================================缺陷2
console.log(arr instanceof Object); //=>true
//=================================缺陷三
function Fn() {}
Fn.prototype = Object.create(Array.prototype);
let f = new Fn;
console.log(f instanceof Array); //=>true f其实不是数组,因为它连数组的基本结构都是不具备的
2.3 constructor
- 用法&检测机制:constructor利用类和实例的关系,实例.constructor 一般都等于 类.prototype.constructor 也就是当前类本身(前提是你的constructor并没有被破坏)
- 特性:不稳定并且不安全
- 缺陷:JS中的constructor是不被保护的(用户可以自己随便改),这样基于constructor检测的值存在不确定性(但是真实项目中,没有人会改内置类的constructor)
- 下面给出一些例子供大家参考
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
-------------------------------华丽的分割性---------------------------------------
介绍了前三种js数据类型检测方法,大家也看到了基本上都存在有一定的缺陷,先面我们介绍一种完美的检测方法。
2.4 Object.prototype.toString.call([value])
JS中基本上不存在局限性的数据类型检测方式: => Object.prototype.toString.call([value]) => 基于它可以有效的检测任何数据类型的值
- 检测机制:
//找到Object.prototype上的toString方法,让toString方法执行,并且基于call让方法中的this指向检测的数据值,这样就可以实现数据类型检测了
//=>Object.prototype.toString.call(10)
// =>({}).toString.call(10)
// =>({}).toString===Object.prototype.toString
//获取结果的结构
//"[object 当前数据值所属的构造函数]"
- 小技巧
//简化字符,利用原型连机制让一个空对象去调用object的toString方法
let class2type = {};
let toString = class2type.toString; //=>Object.prototype.toString
- 下面给出一些例子供大家参考
console.log(toString.call(10)); //=>"[object Number]"
console.log(toString.call(NaN)); //=>"[object Number]"
console.log(toString.call("xxx")); //=>"[object String]"
console.log(toString.call(true)); //=>"[object Boolean]"
console.log(toString.call(null)); //=>"[object Null]"
console.log(toString.call(undefined)); //=>"[object Undefined]"
console.log(toString.call(Symbol())); //=>"[object Symbol]"
console.log(toString.call(BigInt(10))); //=>"[object BigInt]"
console.log(toString.call({xxx:'xxx'})); //=>"[object Object]"
console.log(toString.call([10,20])); //=>"[object Array]"
console.log(toString.call(/^\d+$/)); //=>"[object RegExp]"
console.log(toString.call(function(){})); //=>"[object Function]"
3.拓展一下toString方法和valueOf方法
3.1 valueOf()
- JavaScript调用valueOf方法将对象转换为原始值。你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,JavaScript会自动调用它。例如alert、字符串拼接、把对象转换为数字(都是先调用其valueOf方法获取其原始值然后调用toSting方法转换为字符串)
- 每一种基本数据类型的构造函数的原型上都有valueOf方法,他们都会覆盖此object上的方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。
3.2 toString()
- 每一种数据类型的构造函数的原型上都有toString方法;
- 除了Object.prototype上的toString是用来返回当前实例所属类的信息(检测数据类型的),其余的都是转换为字符串的 对象实例.toString() :toString方法中的THIS是对象实例,也就是检测它的数据类型,也就是THIS是谁,就是检测谁的数据类型
- 下面给出一些例子供大家参考
//这些打印单出的都是数据类型的结构,可以直接查看其构造函数的原型上都包含toString方法
//除了 null 和 undefined之外,所有基本类型都有其对应的包装对象
//==========基本数据类型
console.dir(Number);
console.dir(String);
console.dir(Symbol);
console.dir(Boolean);
console.dir(BigInt);
//=========引用数据类型
console.dir(Array);
console.dir({});
console.dir(RegExp);
console.dir(function(){});
3.3下面通过一道经典面试题带你了解一下这两种方法在js的使用
/*解题思路:
* 1.当将对象b当做属性存入a中,其隐性转换,先调用对象的valueOf方法然后在调用其toString方法
* 最后存入a中的事a[object Object]='我好帅'。
* 2.重复一的步骤,相当于将a[object Object]的值修改成'你好美';
*/
let a={}, b={n:'1'}, c={m:'2'};
console.log(b.valueOf());//{n: "1"}
console.log(b.toString());//[object Object]
a[b]='我好帅';
a[c]='你好美';
console.log(a[b]);//=>'你好美'
结语:
如果觉得对你有帮助,请动动你的小手点个赞鼓励一下我吧.持续更新前端优质内容