站在各路大神与文档的肩膀上,基于自己的理解总结出的一篇文章,描述了 JavaScript 中数据类型检测相关内容。
JavaScript 中的数据类型有 Undefined、Null、Boolean、Number、String、Symbol、BigInt、Object,其中前7种是简单数据类型,而 Object 是引用类型。实际上,Object 中还可以分为 Array、Function、Date、RegExp、Error 等。下面基于以上几种数据类型来说明不同的检测方式及其优缺点。
typeof
typeof 运算符返回一个字符串,表示操作数的类型。它能检测出变量是什么原始类型,但不能检测出引用类型的变量是什么类型的对象。另外,typeof null 也会返回 'object'。
const und = undefined;
const nul = null;
const boo = true;
const num = 1;
const str = 'qwer'
const sym = Symbol()
const bNum = BigInt(9007199254740999)
const obj = new Object();
const arr = [1,2,3];
const fun = () => {}
const date = new Date();
const reg = /a/g;
const err = new Error()
console.log(typeof und); // undefined
console.log(typeof nul); // object
console.log(typeof boo); // boolean
console.log(typeof num); // number
console.log(typeof str); // string
console.log(typeof sym); // symbol
console.log(typeof bNum); // bigint
console.log(typeof obj); // object
console.log(typeof arr); // object
console.log(typeof fun); // function
console.log(typeof date); // object
console.log(typeof reg); // object
console.log(typeof err); // object
instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。instanceof可以用于引用类型的检测,但对于原始类型是不生效的。
console.log(obj instanceof Object) // true
console.log(arr instanceof Array) // true
console.log(fun instanceof Function) // true
console.log(date instanceof Date) // true
console.log(reg instanceof RegExp) // true
console.log(err instanceof Error) // true
constructor
constructor 属性返回 Object 的构造函数(用于创建实例对象)。剔除null、undefined、Symbol、BigInt,constructor 能用于检测 JavaScript 的原始类型和引用类型。
console.log( boo.constructor === Boolean) // true
console.log( num.constructor === Number) // true
console.log( str.constructor === String) // true
console.log( obj.constructor === Object) // true
console.log( arr.constructor === Array) // true
console.log( fun.constructor === Function) // true
console.log( date.constructor === Date) // true
console.log( reg.constructor === RegExp) // true
console.log( err.constructor === Error) // true
如果改变函数原型指向,再利用constructor进行检测时,会发现并不符合预期。
function fun() {}
let f = new fun()
console.log(f.constructor === fun) // true
fun.prototype = new Array()
let f1 = new fun()
console.log(f1.constructor === fun) // false
console.log(f1.constructor === Array) // true
Object.prototype.toString.call()
Object.prototype.toString 最终会返回形式如 [object,class] 的字符串,class 指代的是其检测出的数据类型。
const toString = Object.prototype.toString
console.log(toString.call(und)) // [object Undefined]
console.log(toString.call(nul)) // [object Null]
console.log(toString.call(boo)) // [object Boolean]
console.log(toString.call(num)) // [object Number]
console.log(toString.call(str)) // [object String]
console.log(toString.call(sym)) // [object Symbol]
console.log(toString.call(bNum)) // [object BigInt]
console.log(toString.call(obj)) // [object Object]
console.log(toString.call(arr)) // [object Array]
console.log(toString.call(fun)) // [object Function]
console.log(toString.call(date)) // [object Date]
console.log(toString.call(reg)) // [object RegExp]
console.log(toString.call(err)) // [object Error]
适用性对比
| typeof | instanceof | constructor | Object.prototype.toString.call() | |
|---|---|---|---|---|
| Undefined | √ | 报错 | 报错 | √ |
| Null | × | 报错 | 报错 | √ |
| Boolean | √ | × | √ | √ |
| Number | √ | × | √ | √ |
| String | √ | × | √ | √ |
| Symbol | √ | × | √ | √ |
| BigInt | √ | × | √ | √ |
| Object | × | √ | √ | √ |
| Array | × | √ | √ | √ |
| Function | √ | √ | √ | √ |
| Date | × | √ | √ | √ |
| RegExp | × | √ | √ | √ |
| Error | × | √ | √ | √ |
终极检测方法
/**
* @desc 数据类型检测
* @param v 待检测的数据
* @return {String} 类型字符串
*/
function type(v) {
return Object.prototype.toString.call(v).slice(8, -1).toLowerCase()
}