数据类型检测的几种方法 | 青训营笔记

47 阅读1分钟

这是我参加"第四届青训营"笔记创作活动的第3天

数据类型检测

1.typeof

直接在计算机底层基于数据类型的值(二进制)进行检测,

检测的结果返回的是一个字符串,如:typeof NaN ——>“number”、typeof null ——> "object"、typeof [] ——>"object"、typeof /^$/——>"object"、typeof function(){} ——>"function"

对象存储在计算机中,都是以000开始的二进制存储,null也是,所以检测出来的结果是对象,但null实际不是对象,可以理解为浏览器的一个bug。

typeof 普通对象/数组对象/正则对象/日期对象 ——> "object"

typeof的不足:无法区分具体是什么对象。判断简单数据类型时比较好用。

2.instanceof(检测当前实例是否属于这个类)

如:let arr = [] ;

console.log(arr instanceof Array); //true

console.log(arr instanceod Object); //true

底层机制:只要当前类出现在实例的原型链上,结果都是true。

由于我们可以肆意地修改原型的指向,所以检测出来的结果是不准的。

如:function Fn(){this.x = 100;}

Fn.prototype = Object.create(Array.prototype);

let f = new Fn;

console.log( f , f instanceof Array ); //返回的是true,检测结果错误

不能检测基本数据类型!如:console.log( 1 instanceof Number); //false

面试题:自定义一个instanceof的底层代码让它检测结果变准确

//主要思想:实例.__proto__ ===类.prototype
function instance_of(example,classFunc){
	let classFuncPrototype = classFunc.prototype,
		proto = Object.getPrototypeOf(example);		//代表example.__proto__
	while(true) {
		if(proto === null){
			//Object.prototype.__proto__ =>null
			return false;
		}
		if(proto === classFuncPrototype){
			//查找过程中发现有,则证明实例是这个类的一个实例
			return true ;
		}
		proto = Object.getPrototype(proto);	//找不到就一直向下找,直到Object为止
	}

  let arr = [];
  console.log(instanceof(arr,Array));	//true
  console.log(instanceof(arr,RexExp));	//false
  console.log(instanceof(arr,Object));	//true
  

3.constructor

console.log( arr.constructor === Array); //true

console.log( arr.constructor === RegExp); //false

console.log( arr.constructor === Object); //false

constructor看似比instanceof还好用一些(支持基本数据类型),但是constructor可以随便修改,所以也不准。

4.Object.prototype.toString.call([value])

标准检测数据类型的方法:Object.prototype.toString不是转换为字符串,是返回当前实例所属类的信息。

let obj = { name : '祝福' };

obj.toString() ; =>"[ object Object ]"

typeof与toString相结合的方法——toType:

(
  function () {
    var class2type = {}
    var toString = class2type.toString; //=>Object.prototype.toString
  
    //设定数据类型的映射表
    ['Boolean','Number','String','Function','Array','Date','RegExp','Object','Error',
    'Symbol'].forEach(name => {
      class2type[`[object ${name}]`] = name.toLowerCase();
    });
    console.log(class2type);
    
    function toType(obj){
      if(obj == null){
        // 传递的值是null或者undefined,就返回对应的字符串
        return obj + '';
      }
      // 基本数据类型都采用typeof检测	三目运算
      return typeof obj === 'object' || typeof obj === 'function'?
              class2type[toString.call(obj)] || 'object':
              typeof obj;
    }
    window.toType = toType; //()()闭包包起来进行封装,然后通过这条语句让外面使用
  }
  
)()