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)

相關文章
相關標籤/搜索