javascript內置的類型檢測機制並非完全可靠。比如typeof操作符,並不能准確的判斷數據是哪個類型,比如:數組和對象就不能通過typeof來區分。
typeof [] ==="object" ; // true typeof {} === "object"; // true
但是typeof用來區別對象與基本數據類型時就比較有用了。
基本數據類型檢測
由於typeof對所有對象和數組類型返回的都是"object",所以它在區別對象與基本數據類型時才有用。一個值使用typeof操作符可能返回下列某個字符串,注意是字符串:
"undefined"表示這個值未定義
"boolean"表示這個值是布爾值
"string"表示這個值是字符串
"number"表示這個值是數值
"object"表示這個值是對象或null(注意:typeof null 將返回"object",不能准確地判斷類型的合法性,因此不能用typeof來檢測對象類型。)
"function"表示這個值是函數(注意:Safari第四版在對正則表達式使用typeof操作符時回返回"function",因此很難確定這個值到底是不是函數。)
引用類型檢測
JavaScript引用類型有:Object、Array、Date、Error、RegExp、Function、基本包裝類型(Boolean類型、Number類型、String類型)、單體內置對象(Global對象、Math對象)等。檢測引用類型可以使用 instanceof 和 Object.toString()方法。
instanceof 運算符
instanceof運算符要求其左邊的運算數是一個對象,右邊的運算數則是對象類的名字。如果該運算符的左邊的對象是右邊類的一個實例,則返回true,否則返回false。例如:
var d = new Date(); d instanceof Date; // true d instanceof Object; // true d instanceof Number ; //false var a = []; a instanceof Array ; // true a instanceof Object; // true a instanceof RegExp; // false
但是利用instanceof 操作符確定某個對象是不是數組會有些問題,例如:
if( value instanceof Array ) { // do something }
instanceof 操作符的問題在於,它假定只有一個全局執行環境。如果網頁中包含多個框架,那其實就存在兩個以上不同的全局執行環境,從而存在兩個以上不同的Array構造函數。如果你從一個框架向另一個框架傳入一個數組,那么傳入的數組與在第二個框架中原生創建的數組就會分別具有各自的不同的構造函數。因此在第二個框架對傳入的數組執行 value instanceof Array 就會返回false了,因為構造函數是不一樣的。
Object.toString()檢測對象類型
在任何值上調用原生的toString()方法,都會返回一個[object nativeConstructorName] 格式的字符串。每個類在內部都會有一個[[Class]]屬性,這個屬性就指定上述字符串中的構造函數名。例如:
// 檢測數組類型 function isArray(value){ return Object.prototype.toString.call(value) == "[object Array]" } // 檢測函數 function isFunction(value){ return Object.prototype.toString.call(value) == "[object Function]" } // 檢測正則表達式 function isRegExp(value){ return Object.prototype.toString.call(value) == "[object RegExp]" }
注意:對於在IE中以COM對象形式實現的任何函數,isFunction() 都將返回false,因為它們並非原生的JavaScript函數。
jQuery檢測對象類型也是用到了toString()方法,查看type()方法的實現可以看到:
//version:jquery-1.11.3
var class2type = {};
// Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); });
type: function( obj ) { if ( obj == null ) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call(obj) ] || "object" : typeof obj; }
通過定義一個class2type對象把所有類型的toString()返回值通過鍵值對存儲起來。在調用type方法時通過toString()方法返回值進行匹配,最后返回檢測值的類型。
總結
在區別基本數據類型和對象類型時可以使用typeof運算符,對於對象的類型確定通常使用原生toString()檢測,注意Object.prototype.toString() 本身也可能被修改。
以上是JavaScript類型檢測的一些基礎知識總結,干貨不多,望各位大神指教,歡迎留言討論。