2021 年 09 月 26 日
/** 基本数据类型 */
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
其他都会返回object000
开头代表的是对象,null
表示全零,所以对象的类型被误判为object
.虽然现在的内部类型判断代码已经改变了,但是对于这个Bug缺一直流传下来了
null
拥有自己的Null类型,而引用数据类型中,例如数组、日期、正则、等都有自己的类型,但是typeof返回了其原型链顶端的Objec类型,不能算错误,但是不准确,不是我们想要的值
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判断的是两个对象是否属于实例关系,而不会直接返回数据类型,也就不能准确的判断出数据属于哪种类型。
/** 基本数据类型 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();
};
2021 年 09 月 26 日
Like
Download
Viewed