资讯专栏INFORMATION COLUMN

JS中如何准确判断数据类型

KitorinZero / 2896人阅读

摘要:对于此处的类型都是实例后的对象,并不会深入识别他们的构造函数这里不是数据类型。通过上面的判断,我们知道它并不能满足一些内置构造函数创建的伪类型。

在我的第一篇文章里,介绍过JS各大类型并使用typeof进行输出查看.也有提到过每个函数都有一个自己的内部属性[[class]],这个class指的是js内部分类.这个类的大致包括:数据类型构造函数这两种。

JavaScript类型介绍

我们讲过JS的几大数据类型,也用typeof查看了几个简单的数据类型值。那么今天我们再来更宽泛的了解一下这方面的知识。请看如下代码。
var num = 123;
var str = "aflypig";
var bool = true;
var arr = [1, 2, 3, 4];
var obj = {name:"aflypig", age:21};
var func = function(){ console.log("this is function"); }
var und = undefined;
var nul = null;
var date = new Date();
var reg = /^[a-zA-Z]{5,20}$/;
var error= new Error(); 

显然,上次我们只用typeof查看了几个常用的数据类型,但这次多了一些内置构造函数,还有Array(上次特意没讲Array)类型。那么步入正题,我们怎样才能准确得获得这些(再强调一次,这里不是变量,JS当中衡量类型的是值,变量是储存值的容器)数据类型呢?

其实,一共有四种方法,但能完全准确地识别出它们的只有一种方法,这也是面试过程中屡见不鲜的一道题。

如果判断不同类型 typeof
   typeof num //number
   typeif str //string
   typeof bool //boolean
   typeof arr //object
   typeof obj //object
   typeof func//function
   typeof und //undefined
   typeof nul //object
   typeof date //object
   tyepof reg //object
   tyoeof error //object

解析:typeof可以识别简单基本类型值(比如:number,string,boolean),但对于复合类型(Object,Array,Function)却只能识别Function。

                    undefined和null本身就是JS一直以来的bug,此处typeof `undefined`可以识别出正确的类型值,但null被归类到`Object`大家庭中。
        对于此处的 date && reg && error 类型都是实例后的对象,typeof并不会深入识别他们的`构造函数`(这里不是数据类型)。显然typeof并不能处理这种复杂的类型。

总结:typeof可以看作JS内部已经定义好的各个类型返回其对应的字符串,它不深入值本身,不进行类型转换,只针对于当前值返回其对应的类型值。同样的数据类型通过typeof运算符运算都是一样的,它没有原理可言,JS就是这样定义的,我们只管记死它。

instanceof
通过上面的typeof判断,我们知道它并不能满足一些内置构造函数创建的伪类型。那么,我们这里来使用 constructor 查看他们的构造函数,从而分辨它们的类型。
   num instanceof Number  //false
   str instanceof String   //false
   bool instanceof Boolean   //false
  
        arr instanceof Array  //true
    obj instaneof Object  //true
    func instanceof Function  //true
        und instanceof  Object   //false
        nul instanceof   Object  //false
        date instanceof Date //true
    reg instanceof RegExp //true
    error instanceof Error //true

解析:这里我们使用instanceof来复合判断的是否为对应类型。首先,我们先看false项,num str bool 这三个在使用instanceof 时并没有包装封装对象且instanceof则是根据

constructor
  num.constructor .name    //Numer
  str.constructor.name  //String
  bool.constructor.name  //Boolean
  arr.constructor.name  //Array
  obj.constructor.name  //Objeact
  func.constructor.name  //Function
  und.constructor.name  // TypeError
  nul.constructor.name  //TypeError
  date.constructor.name //Date
  reg.constructor.name // RegExp
  error.constructor.name //Error
上面除了undefined 和 null 类型错误(两者都没有属性值)之外, 其他都可以获得我们想要的数据类型。但实际真的如此吗?
 
  // 1⃣️
  var Structure =  function (){ }
  
  var ins = new Structure();
 
  ins.constructor.name  //Structure 
 
 //2⃣️
  
   var Person = function(){}
   var Student = function(){}
   
   Person.prototype = new Student();
   var obj = new Person();
   
   obj.constructor === Student
 

解析:第一种情况,对于通过我们的构造函数生成的实例,不能准确得获得其对应得类型名称,这一点恐怕就已经遏制了我们使用这种方式。

                    第二种情况,由于对象的构造函数是`可变的`,`不准确的`,我们还是无法准确的通过constructor获得具体的类型.
        
        

总结:通过constructor我们可以得到 instance不能得到的 str num bool 这些基本类型值,但另一个问题又浮现出来,constructor的可变性,由于它的不确定性,我们在很多情况下都无法判断出正确的数据类型,所以使用constructor这个方法也差不多废了....

[[Class]]

解析:此[[class]]指的是隐藏在javascript内部的分类属性,它不可读,不可枚举,不可修改,不可配置。(两边出现__下划线__的属性都属于部分浏览器支持的属性。[[]]两个中括号括起来的属性属于JavaScript内部属性。),我记得上一章说过,JavaScript中一切皆为对象的理念,我们可以强制把它转换成字符串,使它暴露出内部的[[class]]属性。

了解了以上各种方法,我们发现它们只能完成部分的类型验证,有些情况是可变和不准确的。

Object.prototype.toString.call(num);   //  "[object Number]"
Object.prototype.toString.call(str);   //  "[object String]"
Object.prototype.toString.call(bool);  //  "[object Boolean]"
Object.prototype.toString.call(arr);   //  "[object Array]"
Object.prototype.toString.call(func);  //  "[object Function]"
Object.prototype.toString.call(und);   //  "[object Undefined]"
Object.prototype.toString.call(nul);   //  "[object Null]"
Object.prototype.toString.call(date);  //  "[object Date]"
Object.prototype.toString.call(reg);   //  "[object RegExp]"
Object.prototype.toString.call(error);  //  "[object Error]"
 
arr instanceof Array  //true
    obj instaneof Object  //true
    func instanceof Function  //true
        und instanceof  Object   //false
        nul instanceof   Object  //false
        date instanceof Date //true
    reg instanceof RegExp //true
    error instanceof Error //true

我们通过 Object 的 toString 方法来查看了当前对象的数据类型,我们看到使用这种方式可以完美的查看对应的数据类型,正是我们想要的,而且每个对象都有属于自己的[[class]],我们可以理解为,它是JavaScript根据内置构造函数做出的内部分类。

对于这种经常使用原生js又难以需求的情况下,怎么能少得了jqquery呢?

以下是与jQuery.type()函数相关的jQuery示例代码:

jQuery.type( undefined ); // "undefined"
jQuery.type( null ); // "null"
 
jQuery.type( true ); // "boolean"
jQuery.type( new Boolean(true) ); // "boolean"
 
jQuery.type( 3 ); // "number"
jQuery.type( new Number(3) ); // "number"
 
jQuery.type( "test" ); // "string"
jQuery.type( new String("test") ); // "string"
 
jQuery.type( function(){} ); // "function"
jQuery.type( new Function() ); // "function"
 
jQuery.type( [] ); // "array"
jQuery.type( new Array() ); // "array"
 
jQuery.type( new Date() ); // "date"
 
jQuery.type( new Error() ); // "error" // jQuery 1.9 新增支持
 
jQuery.type( /test/ ); // "regexp"
jQuery.type( new RegExp("d+") ); // "regexp"
 

jquery内部也是通过我们刚才说到的 [[class]]的方式实现的,它返回一个字符串,固定为小写字母。
我们可以写行代码,来简单的实现jquery中的type方法

function type(o){
    var s  = Object.prototype.toString.call(o);
    return s.slice(s.indexOf(" ")+1,s.length-1).toLowerCase();
}
 

type(false) //boolean
type({}) //object
type([]) //array
type("") //string
type(/^/) //regexp

 
希望通过本次粗浅的讲解能给大家带来一点收获,在知道最终有适合的方式时,应该多去考虑使用另外的方式去实现的手段,因为做这样可以扩展自己的知识范围。就比如上文,如果从后向前列举,我想有很多人都不会去思考 constructor 和 instance 的不足以及他们的适用范围吧,
 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83090.html

相关文章

  • Js基础知识(一) - 变量

    摘要:内置函数和对象中内置了一些函数和对象,很多语言都会有内置的方法,直接可以调用开发。根据语法标准提供的内置函数包括和。注意基础语法提供的内置函数和方法只有这些,像那是浏览器提供给我们的。强制类型转换大家应该都知道。 js基础 - 变量 *大家对js一定不会陌生,入门很简单(普通入门),很多人通过网络资源、书籍、课堂等很多途径学习js,但是有些js基础的只是往往被大家遗漏,本章就从js变量...

    leone 评论0 收藏0
  • Js基础知识(一) - 变量

    摘要:内置函数和对象中内置了一些函数和对象,很多语言都会有内置的方法,直接可以调用开发。根据语法标准提供的内置函数包括和。注意基础语法提供的内置函数和方法只有这些,像那是浏览器提供给我们的。强制类型转换大家应该都知道。 js基础 - 变量 *大家对js一定不会陌生,入门很简单(普通入门),很多人通过网络资源、书籍、课堂等很多途径学习js,但是有些js基础的只是往往被大家遗漏,本章就从js变量...

    MageekChiu 评论0 收藏0
  • JS类型(三):JS类型检查

    摘要:正文一基本类型检测为什么说是基本类型检测对于这三种类型经常用到的基本类型检测是正确的。为什么说是更好的检测方法上面的两种方法要么是只能检测基本类型,要么是只能检测引用类型,还存在不支持检测的情况。 前言 前两篇文章主要是一直在讨论JS类型的转换,那么怎么才能检测JS的数据类型呢?检测数据类型在工程中经常用到,常见的JS类型检测有三种方法: 1. typeof 2. instanceof...

    ad6623 评论0 收藏0
  • 判断是否是数组的几种方法— (js基础复习第1期)

    摘要:如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。 1. 首先,typeof肯定是不行的 对于一些基本类型,typeof是可以判断出数据类型,但是判断一些引用类型时候,不能具体到具体哪一种类型 再来复习一下typeof的...

    supernavy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<