检测数据类型的几种方法
ECMAscript 中规定的数据类型有:
- 简单类型:string、number、boolean、undefined、null、symbol、bigint
- 引用(复杂)类型:object
object 又分为:普通对象 {}、数组对象 []、函数 function(){}
============================= 分割线 =============================
检测这些数据的类型的方法有:
第一种:typeof 可以检测一些基本的数据类型
语法:typeof 后面加不加括号都是可以用的
注意:正则、{}、[]、null 输出结果为 object
所以这个方法并不是很好
例子:
console.log(typeof /\d/); // object
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof (null)); // object
console.log(typeof 123); // number
console.log(typeof true); // boolean
console.log(typeof function () {}); // function
console.log(typeof (undefined)); // undefined
console.log(typeof(10n)); // bigint
第二种:valueOf
可以看到数据最本质内容(原始值)
例子:
let x = "12345";
let s = new String('12345');
console.log(typeof x); // string
console.log(typeof s); // object
console.log(x == s); // true (typeof检测出来是对象居然和一个数组相等,显然s并不是一个真的对象。)
// 此时看看 valueOf()的表现
console.log(s.valueOf()); // 12345 拿到s的原始值是 字符串的12345
console.log(typeof s.valueOf()) // string 这才是 s 的真正的数据类型
第三种:instanceof 检测当前实例是否隶属于某个类。
双目运算符 a instanceof b ,判断a的构造器是否为b,返回值为布尔值
例子:
function fn() {}
let f = new fn;
console.log(f instanceof fn); // true
console.log(f instanceof Object); // true
let arr = [1,2,3,4];
console.log(arr instanceof Array); // true
第四种:constructor 构造函数
语法:实例.constructor
对象的原型链(===构造函数的原型)下有一个属性,叫 constructor
缺点:constructor 并不可靠,容易被修改(只有参考价值)。即使被修改了,也不会影响代码的正常运行。
正常开发的时候,constructor 不小心被修改了,为了方便维护,和开发,可以手动更正 constructor 的指向。
例子:
function fn() {}
let f = new fn;
console.log(f.constructor.name); // fn
console.log(fn.constructor); // Function(){}
console.log(Function.constructor); // Function(){}
第五种:hasOwnproperty 检测当前属性是否为对象的私有属性,而不是继承自原型链。
语法: obj.hasOwnproperty("属性名(K值)")
例子:
let obj = {
name: "xx"
};
console.log(obj.hasOwnProperty('name')); // true
console.log(obj.hasOwnProperty('xxxx')); // false
扩展:
由于 hasOwnProperty 并非关键字,所以我们很有可能将对象的一个属性命名为 hasOwnProperty,这样一来就无法再使用对象原型的 hasOwnProperty 方法来判断属性是否是来自原型链。
var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // 始终返回 false
不能使用 该对象.hasOwnProperty 这种方法,怎么来解决这个问题呢?我们需要使用原型链上真正的 hasOwnProperty 方法:
({}).hasOwnProperty.call(foo, 'bar'); // true
// 或者:
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
Object.prototype.hasOwnProperty.call(foo, 'bar')
:Object.prototype.hasOwnProperty 在 .call 之后,this 指向了对象 foo,并传入参数 'bar',相当于执行了 foo.hasOwnProperty('bar')
,不同是的是此时的 hasOwnProperty 是我们想要的方法。
第六种:isArray 判断是否为数组、 isNaN() 判断是否是NaN
例子:
console.log(Array.isArray([])); // true
console.log(Array.isArray(new Array())); // true
console.log(isNaN(NaN)) // true
console.log(isNaN(+"12ab")) //true
第七种:Object.portotype.toString (最好的)
语法:Object.prototype.toString.call([value])
获取 Object.portotype 上的 toString 方法,让方法的 this 变为需要检测的数据类型值,并且让这个方法执行
在Number、String、Boolean、Array、Function、RegExp...这些类的原型上都有一个toString方法:这个方法就是把本身的值转化为字符串
(12).toString() // '12'
(true).toString() // 'true'
[12,23].toString() // '12.23'
在Object这个类的原型上也有一个方法toString,但是这个方法并不是把值转换成字符串,而是`返回当前值得所属类详细信息,固定结构:'[object 所属的类]'
var obj = {name: '珠穆朗玛峰'}
obj.toString() // "[object Object]"
调取的正是 Object.prototype.toString 方法
obj.toString()
首先执行 Object.prototype.tostring 方法
这个方法中的 this 就是我们操作的数据值 obj
=>总结:Object.prototype.toString 执行的时候返回当前方法中的 this 的所属类信息
也就是,我想知道谁的所属类信息,我们就把这个toString方法执行,并且让 this 变为我们检测的这个数据值,那么方法返回的结果就是当前检测这个值得所属类信息
Object.prototype.toString.call(12) // "[boject Number]"
Object.prototype.toString.call(true) // "[boject Boolean]"
({}).toString.call([1, 2]) // "[object Array]"
/*
'[object Number]'
'[object String]'
'[object Object]'
'[object Function]'
'[object Undefined]'
'[object Null]'
'[object RegExp]'
'[object Boolean]'
'[object BigInt]'
*/
使用toString检测数据类型,不管你是啥值,我们都可以正常检测出需要的结果(这个方法检测是万能
的)
话外:
1.Math是个对象,不是类。类才有prototype(原型)。也就是说类都有原型:prototype,对象都有原型链:proto,函数既是类,也是对象,也是函数。
2.如何把对象转换成字符串?
对象下的toString方法是检测数据类型的,而不是用来转化成字符串的,这时可以用JSON的方法来转化
{name:'朱军林'}.toString() // => "[object Object]"
JSON.stringify({name:'朱军林'}) // => "{'name':'朱军林'}"