JavaScript 入门之数据类型检测

104 阅读2分钟

站在各路大神与文档的肩膀上,基于自己的理解总结出的一篇文章,描述了 JavaScript 中数据类型检测相关内容。

JavaScript 中的数据类型有 UndefinedNullBooleanNumberStringSymbolBigIntObject,其中前7种是简单数据类型,而 Object 是引用类型。实际上,Object 中还可以分为 ArrayFunctionDateRegExpError 等。下面基于以上几种数据类型来说明不同的检测方式及其优缺点。

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 的构造函数(用于创建实例对象)。剔除nullundefinedSymbolBigIntconstructor 能用于检测 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]

适用性对比

typeofinstanceofconstructorObject.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()
}