数据类型检测

143 阅读2分钟

检测数据类型

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

底层机制:

  1. 只要当前类在该实例的原型链上,其结果都是 true

  2. 它是基于 [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 函数

  1. 封装 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(""));