JS 应用篇(二):判断JS数据类型方法介绍

在ECMAScript规范中,共定义了7种数据类型,分为 基本类型 和 引用类型 两大类,以下所示:javascript

基本类型:String、Number、Boolean、Symbol、Undefined、Null
引用类型:Objecthtml

基本类型也称为简单类型,因为其占据空间固定,是简单的数据段,为了便于提高变量查询速度,将其存储在栈中,即按值访问。java

引用类型也称为复杂类型,因为其值的大小会改变,因此不能将其存放在栈中,不然会下降变量查询速度,所以,其值存储在堆(heap)中,而存储在变量处的值,是一个指针,指向存储对象的内存处,即按址访问。引用类型除 Object 外,还包括 Function 、Array、RegExp、Date 等等。segmentfault

鉴于ECMAScript是松散类型的,所以须要有一种手段来检测给定变量的数据类型。对于这个问题,JavaScript 也提供了多种方法,但遗憾的是,不一样的方法获得的结果良莠不齐。数组

1、typeof方式

typeof是一个操做符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示,包括如下7种:number、boolean、symbol、string、object、undefined、function 等bash

typeof '';// string 符合
typeof 1;// number 符合
typeof Symbol();// symbol 符合
typeof true;//boolean 符合
typeof undefined;//undefined 符合
typeof null;//object 不符合(但愿是null)
typeof [] ;//object 不符合(但愿是array)
typeof new Function();// function 符合
typeof new Date();//object 不符合(但愿是Date)
typeof new RegExp();//object 不符合(但愿是RegExp)
复制代码

有些时候,typeof 操做符会返回一些使人迷惑但技术上却正确的值:app

  • 对于基本类型,除 null 之外,都可以返回正确的结果。
  • 对于引用类型,除 function 之外,一概返回 object 类型。
  • 对于 null ,返回 object 类型。
  • 对于 function 返回 function 类型。

其中,null有属于本身的数据类型Null ,引用类型中的 数组、日期、正则 也都有属于本身的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型,没有错,但不是咱们想要的结果。框架

2、instanceof方式

instanceof是用来判断 A 是否为 B 的实例。函数

表达式为:A instanceof B, 若是 A 是 B 的实例,则返回 true,不然返回 false。在这里须要特别注意的是:instanceof 检测的是原型spa

'' instanceof String; // false
1 instanceof Number; // false
Symbol() instanceof Symbol; // false
true instanceof Boolean; // false
undefined instanceof undefined; // 报错
null instanceof null; // 报错


[] instanceof Array; // true
[] instanceof Object; // true


new Function() instanceof Function; // true
new Function() instanceof Object; // true


new Date() instanceof Date; // true
new Date() instanceof Object; // true
new RegExp() instanceof RegExp; // true
new RegExp() instanceof Object; // true
复制代码

咱们发现,instanceof方式并不能判断出基本类型,并且虽然instanceof可以判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例,为何呢?

咱们来分析一下 [ ]、Array、Object 三者之间的关系:

[ ].__proto__ 指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最终 Object.prototype.__proto__ 指向了null,标志着原型链的结束。所以,[]、Array、Object 就在内部造成了一条原型链:

从原型链能够看出,[] 的 __proto__ 直接指向Array.prototype,间接指向 Object.prototype,因此按照 instanceof 的判断规则,[] 就是Object的实例,依次类推,相似的 new Date()、new Person() 也会造成一条对应的原型链 。所以,instanceof 只能用来判断两个对象是否属于实例关系, 而不可以有效的判断一个对象实例具体属于哪一种类型。

注意:
若是网页中包含多个框架,那实际上就存在两个以上不一样的全局执行环境,从而存在两个以上不一样版本的构造函数。若是你从一个框架向另外一个框架传入一个数组,那么传入的数组与在第二个框架中原生建立的数组分别具备各自不一样的构造函数。

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[0].Array;
var arr =new xArray(1,2,3);// [1,2,3]
arr instanceof Array;// false
复制代码

3、constructor方式

function F(){}
var f = new F()
f.constructor === F // true
复制代码

当一个函数F被定义时,JS引擎会为F添加 prototype 原型,而后再在 prototype上添加一个 constructor 属性,并让其指向F的引用。

当执行 var f = new F() 时,F被当成了构造函数,f是F的实例对象,此时F原型上的constructor传递到了f上,所以 f.constructor == F。当F做为构造函数来建立对象时,原型上的 constructor 就被遗传到了新建立的对象上,从原型链角度讲,构造函数F就是新对象的类型。所以咱们能够根据对象的constructor来判断对象类型。

''.constructor === String; // true
1.constructor === Number; // 报错
Symbol.constructor === Symbol; // false
true.constructor === Boolean; // true
null.constructor === null; // 报错
undefined.constructor === undefined; // 报错
[].constructor === Array; // true
Function.constructor === Function; // true
new Date().constructor === Date; // true
new RegExp().constructor === RegExp; // true
复制代码

注意:

  1. null 和 undefined 是无效的对象,所以是不会有 constructor 存在的,这两种类型的数据须要经过其余方式来判断。

  2. 函数的constructor是不稳定的,这个主要体如今自定义对象上,当开发者重写prototype后,原有的constructor引用会丢失,constructor会默认为Object。

4、Object.prototype.toString方式

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其余对象,则须要经过 call / apply 来调用才能返回正确的类型信息。

Object.prototype.toString.call('') ;  // [object String]
Object.prototype.toString.call(1) ;   // [object Number]
Object.prototype.toString.call(true) ;// [object Boolean]
Object.prototype.toString.call(Symbol());//[object Symbol]
Object.prototype.toString.call(undefined) ;// [object Undefined]
Object.prototype.toString.call(null) ;// [object Null]
Object.prototype.toString.call(new Function()) ;// [object Function]
Object.prototype.toString.call(new Date()) ;// [object Date]
Object.prototype.toString.call([]) ;// [object Array]
Object.prototype.toString.call(new RegExp()) ;// [object RegExp]
Object.prototype.toString.call(new Error()) ;// [object Error]
Object.prototype.toString.call(document) ;// [object HTMLDocument]
Object.prototype.toString.call(window) ;//[object global] window 是全局对象 global 的引用
复制代码

所以,在判断JS数据类型时建议使用Object.prototype.toString方式。

参考:

判断JS数据类型的四种方法

typeof 和 instanceOf的区别

javascript 判断变量是不是数组(Array)

相关文章
相关标签/搜索