在個人第一篇文章裏,介紹過JS各大類型並使用typeof進行輸出查看.也有提到過每一個函數都有一個本身的內部屬性[[class]],這個class指的是js內部分類.這個類的大體包括:數據類型
和構造函數
這兩種。javascript
JavaScript類型介紹 java
咱們講過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當中衡量類型的是值,變量是儲存值的容器)數據類型呢?jquery
其實,一共有四種方法,但能徹底準確地識別出它們的只有一種方法,這也是面試過程當中家常便飯的一道題。面試
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。segmentfault
undefined和null自己就是JS一直以來的bug,此處typeof `undefined`能夠識別出正確的類型值,但null被歸類到`Object`你們庭中。 對於此處的 date && reg && error 類型都是實例後的對象,typeof並不會深刻識別他們的`構造函數`(這裏不是數據類型)。顯然typeof並不能處理這種複雜的類型。
總結:typeof能夠看做JS內部已經定義好的各個類型返回其對應的字符串,它不深刻值自己,不進行類型轉換,只針對於當前值返回其對應的類型值。一樣的數據類型經過typeof運算符運算都是同樣的,它沒有原理可言,JS就是這樣定義的,咱們只管記死它。瀏覽器
經過上面的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
則是根據函數
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這個方法也差很少廢了....this
解析:此[[class]]指的是隱藏在javascript內部的分類屬性,它不可讀,不可枚舉,不可修改,不可配置。(兩邊出現__下劃線__的屬性都屬於部分瀏覽器支持的屬性。[[]]兩個中括號括起來的屬性屬於JavaScript內部屬性。),我記得上一章說過,JavaScript中一切皆爲對象
的理念,咱們能夠強制把它轉換成字符串,使它暴露出內部的[[class]]屬性。prototype
瞭解了以上各類方法,咱們發現它們只能完成部分的類型驗證,有些狀況是可變和不許確的。
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 的不足以及他們的適用範圍吧,