typeof是一元運算符,用來返回操做數類型的字符串。下面是ECAMScript5.1關於typeof的標準定義:javascript
NOTE:上面表格標紅處應爲「object」。java
Value Class Type
-------------------------------------
null null object
"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object
new RegExp("meow") RegExp object
{} Object object
new Object() Object object
NOTE:上面表格中,Class 一列表示對象的內部屬性 [[Class]]
的值,Type 一列表示 typeof
操做符的運算結果。jquery
仔細觀察上面的javascript類型表格,聰明的你也許已經發現了問題所在:type列大多數狀況下都返回 "object"而且和class列的值不一致。所以能夠說typeof運算符能夠用來獲取操做數類型,但極可能得不到想要的結果,因此不該該用typeof來檢測對象的類型。說的這裏你可能會有疑惑了,typeof不能用來檢測對象類型那用來幹嗎,到底該怎麼檢測對象的類型?git
彆着急,先來看看對象的[[Class]]這個內部屬性:github
對於object的內部屬性[[Class]],ECMAScript5.1是這麼說的:ECAMScript規範每種內置對象都定義了 [[Class]] 內部屬性。宿主對象的 [[Class]] 內部屬性的值能夠是"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String" 的任何字符串。[[Class]] 內部屬性的值用於內部區分對象的種類。瀏覽器
NOTE:規範中除了經過 Object.prototype.toString ( ) 沒有提供任何手段使程序訪問此值。ecmascript
明白了,原來能夠經過 Object.prototype 上的toString()方法獲取[[Class]]屬性,[[Class]]屬性就是對象的真正類型,那咱們就來看看Object.prototype.toString ( ) 是何方聖神:ide
是否是有點豁然開朗的感受,因而很快寫出如下代碼:函數
/** * _typeof() returns type of obj * * @obj 要檢測的對象 */ function _typeof(obj) { // Object.prototype.toString 返回一種標準格式字符串("[object ", class, and "]"), // 因此經過 slice 截取指定位置的字符串 return Object.prototype.toString.call(obj).slice(8, -1); } //測試結果 >_typrof([]) ‘Array’ >_typrof(null) ‘null’ >typrof new abc/g ‘RegExp’
到這裏你們也許會想不過如此,若是你真的這麼認爲,只能對你說句Too young Too simple,請往下看:測試
// IE678 Object.prototype.toString.call(null) // "[object Object]" Object.prototype.toString.call(undefined) // "[object Object]"
那麼到底如何正確的判斷javascript的數據類型又作到瀏覽器的兼容呢,聰明的你應該已經想到了jquery,來看看jQuery.type()是怎樣實現的:
var class2type = {}; "Boolean Number String Function Array Date RegExp Object Error".split(" ").forEach(function (e, i) { class2type["[object " + e + "]"] = e.toLowerCase(); }); //固然爲了兼容IE低版本,forEach須要一個polyfill,不做細談了。 function _typeof(obj) { if (obj == null) { return String(obj); } return typeof obj === "object" || typeof obj === "function" ? class2type[class2type.toString.call(obj)] || "object" : typeof obj; } // IE678 >_typrof(null) ‘null’ >_typrof(undefined) ‘undefined
關於數據類型的判斷到這裏就告一段落了,既然typeof不能用做數據類型的判斷,那typeof能夠應用在哪方面呢,往下看。
Typeof會在兩種狀況下返回‘undefined’::一個變量沒有被聲明的時候,和一個變量的值是undefined的時候。
> typeof undeclaredVariable
'undefined'
> var declaredVariable;
> typeof declaredVariable
'undefined'
function isObject(obj) { var type = typeof obj; //typeof把函數和對象當作是不一樣的類型,並且typeof null返回"object" return (type === 'function' || (type === 'object' && !!Obj)); }
function isFunction(obj) { //這樣作是會出現兼容性的問題(IE 11, Safari 8),有興趣的朋友能夠去了解 return typeof obj === 'function'; }
經過本文咱們瞭解到,檢測一個對象的類型儘可能使用Object.prototype.toString()方法,以及如何作到個瀏覽器的兼容性。關於typeof操做符,雖然列舉了幾個典型的應用場景,不過建議除非爲了檢測一個變量是否已經定義,儘可能避免使用typeof操做符。