js数据类型检测方法

151 阅读1分钟

数据类型检测

①typeof

弊端
检测null也返回object
    typeof null ->object
不能细分对象
    typeof [] {} 等返回 ->object
不能细分函数
    typeof function ()=>{} ->function
new出来的基本类型也返回object
typeof new Number(10) ->number

使用场景 做原始值类型检测
    undefined number(NaN) string boolean bigint symbol
console.log(typeof null)//object
console.log(typeof [])//object
console.log(typeof {})//object
console.log(typeof function(){})//function
let fn = ()=>{

}
console.log(typeof fn)//function
console.log(typeof new Number(10))//number

②instanceof

用于细分对象类型
原型链容易被改变,会检测不准
原理是看构造函数身上有没有Symbol.hasInstance([value])属性如果有执行它看返回结果,没有则沿着原型链往上找。
console.log([] instanceof Array)//true
console.log([] instanceof RegExp)//false
console.log([] instanceof Object)//true
//重写instanceof
function myInstanceof(obj,ctor){
    //检测 
    // obj不能为null undefined
    if(obj == null) return false
    //原始值类型直接忽略
    if(!/^(function|object)$/.test(typeof obj)) return false
    //ctor 为null和undefinded是报错
    if(ctor == null) throw new TypeError("Right-hand side of 'instanceof' is not an object")
    //如果原型不存在报错
    if(!ctor.prototype) throw new TypeError("Function has non-object prototype 'undefined' in instanceof check")
    //如果不是函数
    if(typeof ctor !== 'function') new TypeError("Right-hand side of 'instanceof' is not callable")
    let prototype = Object.getPrototypeOf(obj)

    if(ctor[Symbol.hasInstance]){
        return ctor[Symbol.hasInstance](obj)
    }
    while(prototype){
        if(prototype == ctor.prototype) return true
        prototype = Object.getPrototypeOf(prototype)
    }
    return false
}

③constructor

获取对象的构造函数
缺点容易被改变指向
console.log([].constructor == Array)//true
console.log([].constructor == RegExp)//false
console.log([].constructor == Object)//false

④Object.prototype.tostring.call(value)

基本没啥缺点
返回值为 [object number/string/boolean/null/undefined/NaN/bigint/symfbal/function/math...]
[object ?] ?是什么 看value[symbol.toStringTag]返回什么如果没有这个属性,一般返回构造函数
let Fn1 = function(){

}
Fn1.prototype = {
    constructor:'Fn1'
}
console.log(Object.prototype.toString.call(new Fn1))//[object object]
Fn1.prototype = {
    constructor:'Fn1',
    [Symbol.toStringTag] : 'Fn1'
}
console.log(Object.prototype.toString.call(new Fn1))//[object fn1]