检测数据类型
1. typeof
typeof的理解
+ 直接在计算机底层基于数据类型的值(二进制)进行检测,返回的结果是字符串====>1整数 010浮点数 100字符串 110布尔 000对象 -2^30undefined 000000null ...
+ 基于字面量创建的基本类型值其结果都是基本数据类型。基于构造函数创建的基本类型值其结果是 `object`
+ 检测的数组/正则/日期/普通对象的结果是”object“(这是因为对象和null在计算机中是以000二进制开始存储的,所以检测出来的结果相同)
弊端:不能检测对象,数组,日期,正则和 null
2. instanceof 判断类的原型
+ 能具体细分正则/数组/普通对象/日期,
+ 不能检测基本数据类型
例如
let arr = [];
console.log(arr instanceof Array); //true
console.log(arr instanceof Object); //treu
console.log(arr instanceof RegExp); //false
console.log(1 instanceof Number); //false
console.log("" instanceof String); //false
底层机制:
-
只要当前类在该实例的原型链上,其结果都是 true
-
它是基于
[Symbol.hasInstance](实例)
class Fn {
static [Symbol.hasInstance]() {
console.log("OK");
return false;
}
}
let f = new Fn();
弊端:我们可以任意修改当前实例的原型
例如
let arr = [ ];
arr.__proto__ = Object.create(Function.prototype);
console.log(arr instanceof Array); //false
console.log(arr instanceof Object); //true
console.log(arr instanceof Function); //true
3.constructor(类的构造器)
+ 能检测基本数据类型和引用数据类型
+ 但是constructor的值可以任意修改
例如:
let arr = [];
Array.prototype.constructor = "aa";
console.log(arr.constructor === Array); //false
4. Object.prototype.toString.call([value])(标准的检测方法)
-
Object.prototype.toString()不是转化为字符串,而是返回当前实例所属的类信息
-
所属构造函数的信息是根据 Symbol.toStringTag 获取的「有这个属性基于这个获取,没有浏览器自己计算」
function Fn() {}
Fn.prototype[Symbol.toStringTag] = "Fn";
let f = new Fn();
console.log(Object.prototype.toString.call(f)); //->“[object Fn]”
5.封装 instanceof 和检测数据类型 toType 函数
- 封装 instanceof 函数
//=>example:要检测的实例
//=>classFunc:要检测的类
function instance_of(example, classFunc) {
//1. 初始化参数
if (typeof classFunc !== "function")
return new TypeError("classFunc must be an function");
if (example == null) return;
//如果有Symbol这个数据类型就要Symbol处理,否则用原型链处理
//方法一:基于Symbol处理
if (typeof Symbol !== null) {
return classFunc[Symbol.hasInstance](example);
}
//方法二:基于原型链来处理
let proto = Object.getPrototypeOf(example);
if (proto) {
if (proto === classFunc.prototype) {
return true;
}
proto = Object.getPrototypeOf(proto);
}
return false;
}
let res = instance_of([12, 23], Array);
console.log(res); //=>true
2.封装检测数据类型 toType 函数
(function () {
let obj = {};
let toString = obj.toString;
[
"Number",
"String",
"Boolean",
"null",
"undefined",
"Bigint",
"Symbol",
"Array",
"Date",
"RegExp",
"Object",
"Function",
].forEach((item) => {
obj[`[object ${item}]`] = item.toLowerCase();
});
function toType(value) {
if (value === null) {
return value + "";
}
//如果是基本数据类型值用typeof检测,否则用Object.prototype.toString.call([value])
return typeof value === "object" || typeof value === "function"
? obj[toString.call(value)]
: typeof value;
}
window.toType = toType;
})();
console.log(toType(1));
console.log(toType([]));
console.log(toType({}));
console.log(toType(/^$/));
console.log(toType(""));