- 数据类型检测
(1)typeof 检测数据类型的运算符
返回结果是一个字符串,字符串中包含了对应的数据类型" number/string/boolean/undefined/symbol/bigint/object/function" =>typeof typeof xxx 结果都是"string"
存在的BUG
typeof的原理:按照计算机底层存储的二进制结果进行检测的,对象都是以000…开始的。
typeof null “object” =>null的二进制存储值000。
所有对象都是以000开始的,所以基于typeof检测的结果都是"object",也就是typeof无法细分是普通对象还是数组等对象。
(2)instanceof 并不是用来检测数据类型的,是用来检测当前实例是否属于这个类。
用它来检测,一般只应用于普通对象/数组对象/正则对象/日期对象等的具体细分。
<script>
//instanceof实例
let arr=[];
console.log(arr instanceof Array); //true
console.log(arr instanceof Object); //true 不能证明 xxx instanceof Object 是true就是普通对象
console.log(arr instanceof RegExp); //false
</script>
instanceof无法应用到原始值类型数值的检测上
let n=10;
let m=new Number(10);
console.log(n.toFixed(2)); //"10.00" n是Number类的实例,只不过它是字面量方式创造出来的原始值而已(其实n.toFixed(2)的时候,n这个基本类型值浏览器内部也会把它Object(n)一下,然后在调用方法,此时它就具备了__proto__)
console.log(m.toFixed(2)); //"10.00" m也是Number类的实例,只不过它是构造函数方式创造出来的引用类型值而已
console.log(n instanceof Number); //false
console.log(m instanceof Number); //true
原理:
//基于“实例 instanceof 类”检测的时候,浏览器底层是这样处理的“类Symbol.hanInstance”
//Function.prototype[Symbol.hasInstance]=function Symbol.hasInstance{[native code]}
//Symbol.hasInstance方法执行的原理
//根据当前实例的原型链上(proto)是否存在这个类的原型(prototype)
//arr.proto===Array.prototype =>arr instanceof Array :true
//arr.proto.proto===Object.prototype =>arr instanceof Object : true
let arr=[];
console.log(arr instanceof Array); //true
console.log(arr instanceof Object); //true
console.log(Array[Symbol.hasInstance](arr)); //true
//===========
let obj={}
console.log(arr instanceof obj); //报错 因为obj是一个对象,它没有[Symbol.hasInstance]这个属性(函数才可以调用Function.prototype上的这个方法)
(3)constructor:获取实例的构造函数,但是也是可以随意被更改的
let arr=[];
console.log(arr.constructor=== Array); //true
console.log(arr.constructor===Object); //false
(4)Object.prototype.toString.call:专门用来检测数据类型的。
专门用来检测数据类型的
Number/String/Boolean/Symbol/BigInt/Array/RegExp/Date/Function/Object…的原型上都有toString,除了Object.prototype.toString不是转换为字符串,其余都是,Object.prototype.toString是用来检测数据类型的。
返回结果"[object 对象[Symbol.toStringTag || 对象.构造函数 || Object]
- 重写instanceof
//obj要检测的实例对象(不支持原始值类型)
//constructor要检测的类(必须是一个函数)
function instance_of(obj,constructor){
//参数校验
if(obj==null||!/^(object|function)$/i.test(typeof obj)) return false;
if(typeof constructor!=="function") throw new TypeError("Right-hand side of 'instanceof' is not callable");
//obj.__proto__=Object.getPrototypeOf(obj)
let proto=Object.getPrototypeOf(obj),
prototype=constructor.prototype;
while(true){
//找到Object.prototype.__proto__都没有相等的,则证明不是当前类的实例
if(proto===null) return false;
//找到对象的原型链包含类的原型,则证明对象是类的一个实例
if(proto===prototype) return true;
//一级级查找即可
proto=Object.getPrototypeOf(proto);
}
}
console.log(instance_of([],Array)); //true
console.log(instance_of([],Object));//true
console.log(instance_of([],RegExp));//false
console.log(instance_of(10,Number));//false
console.log(instance_of(new Number(10),Number)); //true
console.log(instance_of([],{}));//报错