JavaScript 类型检测
基本数据类型
基本类型有六种: null ,undefined ,boolean ,number ,string ,symbol 。
除了null 以外,基本数据类型使用typeof 运算符即可进行检测。
为什么null 不能检测出
对于 null 来说,虽然它是基本类型,但是会显示 object ,这是一个存在很久了的 Bug。
null 被认为是一个空对象的引用,实际上null 本身是基本数据类型,因为不同的对象在底层都表示为二进制,在JavaScript 中二进制前三位为0的话都会判定为object 类型,而null 的二进制全是0,所以会被判定为object 。
复合数据类型(引用数据类型)
一切引用类型都是对象,对象即属性的集合
对象都是通过函数创建出来的
每个函数都有一个prototype 属性,即原型,这个属性的值是一个对象,这个对象默认只有一个constructor 的属性,指向这个函数本身。
每个对象都有一个__proto__ 属性,即隐式原型。这个属性的值是一个对象,指向了创建这个对象的那个函数,即构造函数。
Object.prototype 指向null ,即原型链顶端。
instanceof 运算符
用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
A instanceof B
规则:沿着A的__proto__ 这条线来找,同时沿着B的prototype 这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true 。如果找到终点还未重合,则返回false 。
let a = {};a instanceof Object;
let a = [];a instanceof Object;
但instanceof 运算符无法检测基本数据类型
自定义实现类型检测
于是需要自己写函数来实现各种数据类型的检测
最开始想通过对象的constructor 对象的name 属性来获取
但意识到constructor 对象的属性在进行class 类定义时可以自行指定,不指定默认为构造函数的名称或类名
class Person{
constructor(){
}
static name = "这是人类";
}
let p1 = new Person();
console.log(p1.constructor.name);
所以这种想法不行
利用Object.prototype.toString 检测类型
于是选择最通用的方法
原理是通过Object.prototype.toString 方法
function myTypeOf(target) {
if (target === null) {
return "null";
} else if (typeof target === "object") {
return Array.from(Object.prototype.toString.call(target)).slice(8,-1).join('').toLocaleLowerCase();
} else {
return typeof target;
}
}
console.log(myTypeOf(null));
console.log(myTypeOf(undefined));
console.log(myTypeOf('123'));
console.log(myTypeOf(123));
console.log(myTypeOf(true));
let ss = Symbol();
console.log(myTypeOf(ss));
let set = new Set();
console.log(myTypeOf(set));
let map = new Map();
console.log(myTypeOf(map));
console.log(myTypeOf([1, 2, 3]));
console.log(myTypeOf({ name: 'zs' }));
完成!
|