JS的數據類型分爲基本類型和引用類型:
基本類型:String,Boolean,Number,Null,Undefined,Symbol(Symbol爲ES6新增)
引用類型:Object(其中包含了Array,Date,Function等)數組
下面會介紹經常使用的四種判斷方法:app
typeof
typeof做爲一個操做符,右邊跟一個表達式,並返回這個表達式的數據類型。typeof A,判斷A的數據類型
對於基本類型,除了null都可返回正確的結果。
對於引用類型,除了function可正確返回,其餘的返回結果均爲Object類型。
所以若是對String,Boolean,NUmber,Undefined,Symbol,Function的類型判斷能夠用typeof
如下爲示例:框架
//可返回想要的結果 typeof "a" //"string" typeof true //"boolean" typeof 1 //"number" typeof undefined //"undefined" typeof Symbol() //"symbol" typeof function a(){} //"function" //不可返回想要的結果 typeof null //object typeof [] //object typeof new Date() //object
instanceof
instanceof是用來檢測構造函數的prototype屬性是否出如今某個實例對象的原型鏈上,簡而言之就是判斷A是否爲B的實例,A instanceof B,若是A是B的實例,則返回爲true,不然返回爲false
對於基本類型,沒法用instanceof正確判斷。判斷null和undefined會直接報錯
對於引用類型,也不夠嚴謹。
instanceof判斷的是是否處於原型鏈上,而不是是否是處於原型 鏈最後一位,所以它並不能判斷一個對象實例具體屬於哪一種類型。例如 雖然instanceof能夠判斷出[]是Array的實例,但它認爲[]也是 Object的實例,[],Array,Object在內部造成了一條原型鏈
如下爲示例:函數
function A(){} var a = new A(); a instanceof A;//true,由於A.prototype在a的原型鏈上 1 instanceof Number //false "" instanceof String //false Symbol() instanceof Symbol //false true instanceof Boolean //false null instanceof Null VM137:1 Uncaught ReferenceError: Null is not defined at <anonymous>:1:17 (anonymous) @ VM137:1 undefined instanceof Undefined VM200:1 Uncaught ReferenceError: Undefined is not defined at <anonymous>:1:22 (anonymous) @ VM200:1 [] instanceof Array //true [] instanceof Object //true new Date() instanceof Date //true new Date() instanceof Object //true
instanceof還有一個問題就是它假定只有一個全局執行環境,如 果網頁中包含多個框架,那實際上就存在多個不一樣全局執行環境,從而 存在兩個不一樣版本的構造函數,若是從一個框架向另外一個框架傳入數 組,那麼傳入的數組與在第二個框架中原生態建立的數組分別具備各自 不一樣的構造函數。
如下爲示例:spa
var iframe=document.createElement("iframe") document.body.appendChild(iframe); iframeArray = window.frames[0].Array; var arr = new iframeArray(1,2);//[1,2] arr instanceof Array //false arr instanceof iframeArray //true
針對這個問題,能夠用ES5提供的Array.isArray()方法,它不會區分對象是在哪一個環境下建立的prototype
constructorcode
當一個函數被定義時,JS引擎會爲它添加prototype原型,而後再在prototype上添加一個constructor屬性,並讓其指向函數的引用,以下圖所示,咱們建立一個名爲A的函數:
當咱們new一個A的實例時,var a = new A();A被當成了構造函數,a是A的實例對象,此時A原型上的construct被傳遞到了A上,所以a.construct = A對象
A利用原型對象上的construct引用了自身,當A做爲構造函數來建立新的對象,原型上的construct屬性就會被新建立的對象繼承,從原型鏈角度講,構造函數A就是新建立對象的數據類型,這樣作的意義是,讓新對象在生成時,都有可追溯的數據類型。一樣,JS的內置對象在生成時也是這樣的
如下爲示例,由於null和undefined時無效的對象,因此它們不會有constructor,因此會報錯。blog
"1".constructor == String //true true.constructor == Bollean // true Symbol().constuctor == Symbol // false [1].constructor == Array //true [1].constructor == Object //false new Date().constructor == Date //true new Function().constructor == Function //true 1.constructor == Number VM505:1 Uncaught SyntaxError: Invalid or unexpected token VM587:1 Uncaught ReferenceError: Bollean is not defined at <anonymous>:1:21 (anonymous) @ VM587:1 null.constructor == NULL VM636:1 Uncaught TypeError: Cannot read property 'constructor' of null at <anonymous>:1:6 (anonymous) @ VM636:1 undefined.constructor == Undefined VM698:1 Uncaught TypeError: Cannot read property 'constructor' of undefined at <anonymous>:1:11 (anonymous) @ VM698:1
從示例中能夠看出,彷佛咱們能夠用construct判斷String,Bollean,Array,Date,Function等,可是實際上函數的constructor是不穩定的,當被調函數的prototype被重寫後,再次實例化,原有的constructor會變成Object,爲了開發規範,在重寫對象原型時,通常都須要從新給constructor賦值,以保證對象實例的類型不被更改。繼承
function A(){} a = new A() a.constructor == A //true A.prototype = {}; b = new A(); b.constructor == A //false b.constructor == Object //true a.constructor == Object //false
Object.prototype.toString.call()
這個方法時最準確最經常使用,每個繼承Object的對象都有toString方法,若是toString方法沒有被重寫的話,會返回[Object type],其中type爲對象的類型,但當除了Object類型的對象外,其餘類型直接使用toString方法時,會直接返回都是內容的字符串,因此咱們須要call或者apply方法來改變toString方法的執行上下文,使用Object.prototype上的原生toString()方法判斷數據類型。
如下爲示例:
Object.prototype.toString.call() //"[object Undefined]" Object.prototype.toString.call("a") //"[object String]" Object.prototype.toString.call(true) //"[object Boolean]" Object.prototype.toString.call(1) //"[object Number]" Object.prototype.toString.call(1.1) //"[object Number]" Object.prototype.toString.call(null) //"[object Null]" Object.prototype.toString.call(undefined) //"[object Undefined]" Object.prototype.toString.call([1]) //"[object Array]" Object.prototype.toString.call(new Date()) //"[object Date]" Object.prototype.toString.call(Symbol()) //"[object Symbol]" Object.prototype.toString.call(function a(){}) //"[object Function]" Object.prototype.toString.call(new Function()) //"[object Function]"