[javascript核心-09] 彻底解决js中的类型检测方案

87 阅读2分钟

本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士

typeof

  1. 基于数据类型的值(二进制)进行检测
  2. 返回结果为字符串
  3. typeof NaN结果为number
  4. typeof null结果为Object.对象存储以000开头,而null也是如此。
  5. typeof不能细分对象,结果都是Object
  6. typeof function(){}结果为function

instanceof

  1. 检测某个构造函数是否出现在某实例的原型链上
  2. 返回结果为boolean值
  3. [] instanceof Arraytrue, [] instanceof Objecttrue。原型可手动修改,因此检测结果也会被篡改。
  4. 不能检测基本数据类型。1 instanceof Numberfalse

constructor

  1. 检测某个函数是否是某实例的构造函数
  2. 返回结果为boolean值
  3. 可以检测基本数据类型
  4. constructor可手动修改,因此检测结果也会被篡改。

Object.prototype.toString.call()

  1. 返回当前实例所属类的信息
Object.prototype.toString.call(1) // '[object Number]'
Object.prototype.toString.call('1') // '[object String]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(Symbol(1)) // '[object Symbol]'
Object.prototype.toString.call(/^/) // '[object RegExp]'
Object.prototype.toString.call(new Date) // '[object Date]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call(()=>{}) // '[object Function]'
Object.prototype.toString.call(1n) // '[object BigInt]'
Object.prototype.toString.call(new Error()) // '[object Error]'

最佳实践

  1. typeof 可以检测基本数据类型的值(除 Null 以外)
  2. 其他的类型可以用Object.prototype.toString.call()

封装数据类型检测的方法

目标:能够对Number,String,Boolean,Null,Undefined,Symbol,RegExp,Date,Array,Object,Function,Error,BigInt全部类型值进行细分检测。

类型检测函数

function toType(obj){
    const classType = {};
    ['Number','String','Boolean','Null','Undefined','Symbol','RegExp','Date','Array','Object','Function','Error','BigInt'].forEach(name => {
        classType[`[object ${name}]`] = name.toLowerCase()
    });

    function _toType(obj){
        if(obj == null) return obj + ''
        return typeof obj === 'object' || typeof obj === 'function' ? classType[toString.call(obj)] || 'object' : typeof obj
    }
    return _toType(obj)
}

进行测试:

// 测试
[1,'1',true,null,undefined,Symbol(1),/^/,new Date(),[],{},()=>{},new Error(),100n].forEach(obj => {
    console.log(toType(obj))
})

/*
number
string
boolean
null
undefined
symbol
regexp
date
array
object
function
error
bigint
*/

建立映射表进行比对:

const map = [
    [1,'number'],
    ['1','string'],
    [true,'boolean'],
    [null,'null'],
    [undefined,'undefined'],
    [Symbol(1),'symbol'],
    [/^/,'regexp'],
    [new Date(),'date'],
    [[],'array'],
    [{},'object'],
    [()=>{},'function'],
    [new Error(),'error'],
    [100n,'bigint']
]

for (const tuple of map) {
    console.log(toType(tuple[0]) === tuple[1])
}

/*
true
true
true
true
true
true
true
true
true
true
true
true
true
*/

本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士