js数据类型检测(一次性讲清楚)

(1)四种常见方案

  • typeof
  • instanceof
  • constructor
  • Object.prototype.toString.call(value)

(2)typeof

  • 原理
    typeof是在计算机底层根据js数据类型的二进制的值进行检测的。在JavaScript中,用32个二进制位来标识JavaScript中的值,其中低三位来表示值的类型。000表示对象,010表示浮点数,100表示字符串,110表示布尔值,001表示整数,-2^30表示undefined,全0表示null。
  • 类型判断结果
    valuetypeof value
    数值/NaN/Infinity‘number’
    字符串‘string’
    true/false‘boolean’
    undefined‘undefined’
    null‘object’
    大整数‘bigint’
    Symbol类型‘symbol’
    函数‘function’
    非函数对象‘object’
  • 总结
    从上面表格可以发现typeof能较好地判断基本数据类型(null除外);而对于引用数据类型,则只能判断function类型的数据。
  • 问题1:typeof null 检测出来的结果为什么是object?
    typeof是根据二进制值来判断数据类型的,null 的二进制值是全0,而 object 类型的二进制值都是 000 开头的,所以typeof检测null时也被检测成object。(可以理解为这是JavaScript历史遗留下来的bug)
  • 问题2:为什么typeof判断函数可以判断出是function类型(而不是object)?
    虽然在JavaScript中函数也是对象,但是在进行typeof判断时候,如果遇到函数时会自动调用call方法来判断。

(3)instanceof

  • 原理
    只要当前类在被检测的实例的原型链上,结果都是true。

      console.log([] instanceof Array)//true
      console.log([] instanceof RegExp)//false
      console.log([] instanceof Object)//也是true
    

    最后一行可能有人觉得奇怪,后续我会花专门章节分析原型链相关知识。在这大致解释起来就是空数组[]这个被检测的实例的原型链上有Array、Object。

  • 一些弊端
    可以肆意修改原型的指向,会导致检测出来的值可能不准确

    function Fn(){
       this.x=10;
     }
     Fn.prototype=Object.create(Array.prototype);
     let f=new Fn();
     console.log(f instance Array)//true
    

    并且instanceof不能检测基本数据类型。

  • 手写instanceof

    function myInstance(example,classFunc){
      // 实例.__proto__===类.prototype
      if(typeof example !=="object" || example ===null){
          return false;
      }
      //获取参数的原型对象
      let proto=Object.getPrototypeOf(example);
      //这里没有用 example.__proto__,因为IE浏览器不兼容
      while(true){
        if(proto===null){
          return false;
        }
        if(proto===classFunc.prototype){
          return  true;
        }
         proto=Object.getPrototypeOf(proto)
      }
    }
    

(4)constructor

  • 用起来比instanceof似乎好一些(也支持基本数据类型)
       let arr=[];
       console.log(arr.constructor===Array);//true
       console.log(arr.constructor===RegExp);//false
       console.log(arr.constructor===Object);//false
       let n=1;
       console.log(n.constructor===Number);//true
    
  • constructor可以随意改变,所以也不准确
      Number.prototype.constructor="AA";
      let n=1;
      console.log(n.constructor===Number);//false
    

(5)Object.prototype.toString.call(value)

  • Object.prototype.toString不是转换为字符串,是返回当前实体所属类的信息,call是改变this指向
  • 可以检测所有类型的值
     [object Number]
     [object String]
     [object Boolean]
     [object Null]
     [object Undefined]
     [object Symbol]
     [object Object]
     [object Array]
     ...等等
    

(6)封装一个检测数据类型的方法

  • 思路
    基本数据类型用typeof判断,引用数据类型用Object.prototype.toString.call判断
  • 代码
    function getType(obj){
      //简约undefined和null
      if (obj==null){
        return obj+"";
      }
      if (typeof obj =='object' || typeof obj =='function'){
        let typeStr = Object.prototype.toString.call(obj)
        // 解析[object String]
        typeStr = typeStr.split(' ')[1]
        type = typeStr.substring(0, typeStr.length - 1)
         return  type.toLowerCase();
      }
      return  typeof obj;
    }
    
  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值