Js检测数据类型

2021 年 09 月 26 日

Js

typeof()

/** 基本数据类型 */
let a = 99                // 理论:number        结果:number      有效
let str = '这是字符串'      // 理论:string        结果:string      有效
let und= undefined        // 理论:undefined     结果:undefined   有效
let blean = true          // 理论:boolean       结果:boolean     有效
let sym = Symbol()        // 理论:Symbol        结果:symbol      有效
let nul = null             // 理论:null         结果:object      无效
/** ES10新增Bigint类型 */
var int = Bigint(100);
typeof int = bigint;            // 理论:bigint         结果:bigint     有效

/** 引用数据类型 */
let obj = {a:1,b:2}       // 理论:object      结果:object        无效
function fn() {}          // 理论:function    结果:理论:function 无效
let arr = [1,2,3]         // 理论:array       结果:object        无效

总结

  • 对于基本数据类型, 除了null其他都会返回正常的结果
  • 对于引用数据类型,除了function其他都会返回object
  • 对于null,会返回object,历史遗留问题,也是bug,原因在于JS初始版本使用的是32位系统,为了性能考虑使用低位存储变量的类型信息,而000开头代表的是对象,null表示全零,所以对象的类型被误判为object.虽然现在的内部类型判断代码已经改变了,但是对于这个Bug缺一直流传下来了
  • 对于function会返回function

null拥有自己的Null类型,而引用数据类型中,例如数组、日期、正则、等都有自己的类型,但是typeof返回了其原型链顶端的Objec类型,不能算错误,但是不准确,不是我们想要的值

instanceof

instanceof是用来检测A是不是B的实例,表达式是A instance B,返回的是boolean,instanceof检测的是原型,所以他的检测方式是,查看A的prototype是否出现在B的__proto__ 上,也可以理解为A的是否是B的实例。

/** 基本数据类型 number string undefined boolean Symbol bull */
let a = 99                // 理论:false        结果:false       错误
let str = '这是字符串'      // 理论:false        结果:false       错误
let und= undefined        // 理论:报错          结果:报错         错误
let blean = true          // 理论:false        结果:false       错误
let sym = Symbol()        // 理论:false        结果:symbol      错误
let nul = null             // 理论:报错         结果:报错         错误

/** 引用数据类型 array function object */
let obj = {a:1,b:2}       // 理论:true       结果:true       正确
function fn() {}          // 理论:true       结果:true       正确
let arr = [1,2,3]         // 理论:true       结果:true       正确

总结

  • 通过打印可以发现,instanceof对于基本数据类型全部返回false,所以是错误的,单纯的定义一个字面量是无法通过instanceof进行检测的,如果我们要对其检测,需要通过new方式,就可以了。

    let str = new String('我是字符串')
    console.log(str instanceof String) //true
    
  • 检测引用数据的类型全部正确,所以一般来讲这个方法我们是用于检测引用数据类型的。

原理

console.log([] instanceof Object) //true

例如上面这个检测过程 我们可以理解为

[].prototype => Array.prototype => Object.prototype

数组的原型会指向Array.prototype,间接的指向了Object.prototype,所以[]也属于对象返回正确,所以说instanceof判断的是两个对象是否属于实例关系,而不会直接返回数据类型,也就不能准确的判断出数据属于哪种类型。

Object.prototype.toString.call()

/** 基本数据类型 number string undefined boolean Symbol bull */
let a = 99                // 理论:number        结果:Number      正确
let str = '这是字符串'      // 理论:string        结果:String      正确
let und= undefined        // 理论:undefined     结果:Undefined   正确
let blean = true          // 理论:boolean       结果:Boolean     正确
let sym = Symbol()        // 理论:Symbol        结果:Symbol      正确
let nul = null             // 理论:null         结果:Null        正确
let int = Bigint(99)       // 理论:bigint       结果:bigint        正确

/** 引用数据类型 array function object */
let obj = {a:1,b:2}       // 理论:object      结果:Object       正确
function fn() {}          // 理论:function    结果:Function     正确
let arr = [1,2,3]         // 理论:array       结果:Array        正确

可以看出通过Object.prototype.toString.call(xx)的检测结果对于这些基础数据类型都是正确的,一般来讲,在常用的检测数据类型中,这种事最为准备的方法,那么是如何实现呢

原理

首先我们看看传统的toString()方法和Object原型上的toString()有何区别

var arr = [1,2,3]
console.log(Object.prototype.toString.call(arr)) //[object Array]
console.log(arr.toString()) // 1,2,3

可以看出传统的toString()是吧arr转换成字符串了,并不能够检测类型,所以看完这个大家应该明白,直接Object.prototype上面的toString才可以检测数据类型。这里也涉及到原型链的知识,我们分析一下:

首先arr.toString调用的是Array.prototype上面的toSting(),虽然Array也继承与Object但是这个方法在Array上进行了重写,所以两个toString也是不一样的,所以当我们 .toString.call(arr)的时候就调用的是Object的原型上面的toString,所以可以判断出对象类型

注意

  • {}调用传统的toString()返回的不是{},是*[object Object]*

    var strb = {}
    console.log(strb.toString()) // [object Object]
    
  • 原始类型为什么可以调用呢?

    var num = 123;
    /** .toString();—系统内部经过包装类包装–>new Number(num).toString(); */
    /** 包装类: new Number(); new String(); new Boolean()  */
    

    原始类型在调用前都会经过new去包装成类,所以就可以用过原型去找到toString。

  • 包装类也是对象,既然都是对象为什么调用toString()返回结果不一样?

    我们知道继承可以拿到object原型上的toString的方法,可以判断数据类型,但是并不能满足我们的其他需求,所以作为子类的包装类就重写了toString方法,所以当我们调用时就会调用自身重写的方法,直接我们通过call指向Object原型的时候才可以去正在的判断类型。

  • 需要注意的是 检测类型的返回值并不是直接可以使用 是这种格式的[object Array],需要自己进行处理,后面的就是我们的格式

封装

日常开发中,最为准确的就是第三中方法,所以,这里我们来封装一个检测数据类型的方法:

var tsType = function (data){
    var s = Object.prototype.toString.call(data);
    return s.match(/\[object (.*?)\]/)[1].toLowerCase();
  };
  • 基本数据类型目前有 number、string、undefined、null、boolean、Symbol、Bigint、七种类型
  • 引用数据类型泛指 object,object包含了多种数据类型,例如,Function、Array、RegExp、Date、Map、Set类型等等

交流专区 文明发言

Js检测数据类型

2021 年 09 月 26 日

0

Like

0

Download

147

Viewed