判斷一個數據的類型,常用的方法有以下幾種:
typeof
instanceof
Object.prototype.toString.call(xxx)
下面來分別分析一下這三種方法各自的優缺點
typeof
typeof
的本意是用來判斷一個數據的數據類型,所以返回的也是一個數據類型。但是會遇到下面這些問題:
- 無法判斷
null
。 - 無法判斷除了
function
之外的引用類型。
// 無法判斷 null。
console.log(typeof null); // 輸出 'object',原因在文章末尾解釋。// 無法判斷除了 function 之外的引用類型。
console.log(typeof []); // 'object'
console.log(typeof {}); // 'object'
incetance of
可以看到,type of
無法精確判斷對象的引用類型。所以在判斷一個對象的引用類型時一般使用incetance of
關鍵字。
console.log([] instanceof Array); // true
console.log(str1 instanceof String); // false,無法判斷原始類型。
但是incetance of
無法準確判斷原始數據類型,只能用來判斷數據是否是某個類的引用。到這里就能發現,如果把incetance of
和type of
結合起來基本就能判斷所有的數據類型了。
但是,別忘記還有一個null
,對于null
還需要進行特殊的處理。
typeof null; // objectif (target === null) {return "null";
}
結合這兩種方法基本已經掌握了判斷數據類型的手段了,但是如果去寫一下你還是會發現很麻煩,你必須枚舉每一種類型利用true
orfalse
判斷數據類型。
這里的null
必須單獨判斷,因為這是第一版JavaScript
留下來的一個bug。
JavaScript 中不同對象在底層都表示為二進制,而 JavaScript 中會把二進制前三位都為 0 的判斷為 object
類型,而 null
的二進制表示全都是 0,自然前三位也是 0,所以執行 typeof
時會返回 'object'
。
這個 bug 牽扯了太多的 Web 系統,一旦改了,會產生更多的 bug,令很多系統無法工作,也許這個 bug 永遠都不會修復了。
Object.prototype.toString.call(xxx)
這個時候就不得不提到下面這種方法了:
Object.prototype.toString.call([]) // [object Array]
這個方法會返回統一格式的字符串:[object Xxx]
。然后再取出后面的xxx
即可得到準確的數據類型。對于取出后面的xxx
可以使用多種方法,包括但不限于字符切片、正則表達式。
這里調用
call()
方法是為了讓this
指向數組對象自身。