JS中怎样正确推断数据类型

在我的第一篇文章里,引见过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://segmentfault.com/a/1190000009476174
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞