JS数据类型检测

206 阅读1分钟

JS数据类型检测

一.检测类型之前我们需要知道js中有哪些数据类型

一般来说数据类型分为两种:基本数据类型和复杂数据类型

基本数据类型

  • String
  • Number
  • Boolen
  • Null
  • Undefined
  • Symbol
  • BigInt

复杂数据类型

  • Object
  • Array
  • Function
  • Date
  • RegExp

二.检测数据类型的方法

  • typeof

typeof 运算符返回一个字符串,表示操作数的类型。

/* 基本数据类型 */
console.log(typeof '') //string
console.log(typeof 1) //number
console.log(typeof true) //boolen
console.log(typeof undefined) //undefined
console.log(typeof null) //object
console.log(typeof Symbol()) //symbol
//看完上面的输出结果肯定会有疑问,都是基本数据类型为啥 typeof null 是object呢?
/*
   在javascript最开始使用的是32位系统,js为了性能优化使用低位来储存类型信息
   object: 000.
   int: 1
   double:010
   string:100  
   boolen:110
   null:全是0
   所以导致 typeof null 为object
*/
/* 复杂数据类型*/
//typeof 判断复杂数据类型除function外都是object,不能准确判断复杂数据类型
console.log(typeof []) //object
console.log(typeof {}) //object
console.log(typeof new RegExp(/^$/)) //object
console.log(typeof new Date()) //object
console.log(typeof function (){}) //function

  • instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

//instanceof本质是来判断构造函数的prototyoe有没有在实例的原型链上的,但是我们可以根据这个特性来判断数据类型。
 console.log([] instanceof Array) //true
 console.log({} instanceof Object)//true
 console.log(new Date() instanceof Date)//true
 console.log(new RegExp() instanceof RegExp)//true
 //当然用instanceof判断类型也有缺陷:
 console.log([] instanceof Object) //true 因为跟据原型链查找机制最终会查找到Object.prototype,所以数组的原型链上会出现Object
 console.log(new Number(1) instanceof Object)//true 为什么用 new Number 因为1是一个原始值并不是一个对象,所以需要用new Number来声明
/* 下面来实现一个instanceof */
  function myInstanceof(example,classFnc){
   if(example == null) return false;//排除 null undefined 原始方法里面并没有排除。
   if(typeof example !== 'object' && typeof example !== 'function') return false;
   var getProto = Object.getPrototypeOf,
       classFncProto = classFnc.prototype,//拿到构造函数的prototype
       exampleProto = getProto(example);//获取实例的prototype;
   while(true){
      if(exampleProto === null) return false //一直找到Object.prototype.prototype为null,这样说明没有找到返回false
      if(exampleProto === classFncProto) return true// 如果相等则返回true
      exampleProto = getProto(exampleProto)//获取实例prototype的prototype
   }
  }
  console.log(myInstanceof(1,Number))//false
  console.log(myInstanceof(new Number(1),Number))//true
  console.log(myInstanceof([],Array))//true
  console.log(myInstanceof([],Object))//true
  console.log(myInstanceof(new Date(),Date))//true
  • constructor

Object 实例的 constructor 数据属性返回一个引用,指向创建该实例对象的构造函数。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。

//我们可以通过实例的constructor指向实例对象的构造函数来判断数据类型检测,constructor比instanceof好的地方在于可以检测基本类型 undefined、null除外
var num = 1;
console.log(num.constructor === Number)//true;
var str = 'str';
console.log(str.constructor === String)//true
var bool = true;
console.log(bool.constructor === Boolean)//true
//而且constructor不会顺着原型链查找
let arr = []
console.log(arr.constructor === Array)//true
console.log(arr.constructor === Object)//false

//当然也有缺点就是constructor可以被随意更改
let obj = {};
obj.constructor = 'AAA';
console.log(obj.constructor === Object);//false 此时obj.constructor : AAA
  • Object.prototype.toString

Object.prototype.toString() 返回 "[object Type]",这里的 Type 是对象的类型

// 用这种方法来判断数据类型能精确的判断出数据类型
console.log(Object.protoType.toString(1))//"[object Number]"
console.log(Object.protoType.toString(''))//"[object String]"
console.log(Object.protoType.toString(true))//"[object Boolean]"
console.log(Object.protoType.toString(null))//"[object Null]"
console.log(Object.protoType.toString(undefined))//"[object Undefined]"
console.log(Object.protoType.toString(function(){}))//"[object Function]"
console.log(Object.protoType.toString([]))//"[object Array]"
console.log(Object.protoType.toString({}))//"[object Object]"
console.log(Object.protoType.toString(new Date()))//"[object Date]"
console.log(Object.protoType.toString(Math))//"[object Math]"
console.log(Object.protoType.toString(new RegExp()))//"[object RegExp]"
//当然此方法也有缺点ES6之后内置对象type都是根据Symbol.toStringTag来取,所以导致能更改
const myDate = new Date();
Object.prototype.toString.call(myDate); // [object Date]
myDate[Symbol.toStringTag] = "myDate";
Object.prototype.toString.call(myDate); // [object myDate]

封装类型检测方法

最后用我们所了解的的类型检测方式封装一个简单的类型检测方法

/**
 * @param {*} tarValue 目标值
 * @returns {string} tarType 返回目标类型 
 */
   function detectionType(tarValue){
      if(typeof tarValue !== 'object' || tarValue === null) return tarValue + '';
      var reg = /^\[object (.+?)\]$/;
      var typeStr = Object.prototype.toString.call(tarValue);
      return typeStr.match(reg)[1].toLowerCase();
   }