因為JavaScript是一門弱引用類型的語言,所以在開發過程中我們常常會遇到 “我定義的這個變量是什么數據類型?”這種類似的問題,所以今天我們來看看在JS中一般用什么方式來判斷數據類型的。
1、typeof
這個方法還是比較常用的,一般用它來判斷基本數據類型,比如 String
,Number
,Boolean
,Symbol
,Object
,Null
,Undefined
:
這里需要特別說明一下,對于對象(引用對象)類型的判斷往往并不是我們想要的結果,換句話說,就是我只知道他是對象類型,但是不知道是什么對象,比如:
可能大家還會比較奇怪,為什么 Null
的數據類型竟然是object,去查閱了一番,才知道這竟然是 “打小” 就是這樣設計的,在JS中聲明的變量在底層的表現形式都是二進制,而二進制前三位都為0的話就會被判斷成object類型,而 Null
的所有機器碼都是0,所以就會被當成對象來看了。順便在這里拋一個小問題:
Number(null) = ?
對這塊有興趣的可以深入研究一下。
2、instanceof
這個方法,相信寫Java的童鞋并不陌生,這個方法主要是用來判斷一些引用數據類型,比如 Function
,Array
,Date
:
instanceof
主要就是判斷一個引用實例是否屬于某種類型,簡單來說就是判斷兒子是否屬于該父親。但是 instanceof
不僅僅是能判斷父子關系,還能判斷爺孫關系,甚至更多層的關系。那么它的原理是什么呢?
function instanceof(left, right) {
const rightVal = right.prototype
const leftVal = left.__proto__
// 若找不到就到一直循環到父類型或祖類型
while(true) {
if (leftVal === null) {
return false
}
if (leftVal === rightVal) {
return true
}
leftVal = leftVal.__proto__ // 獲取祖類型的__proto__
}
}
判斷原理就是只要右邊變量的 prototype
在左邊變量的原型鏈上即可,在這個判斷過程中會一直遍歷左邊變量的原型鏈(父組件,祖組件)直到查找結束,如果失敗就返回false。
3、prototype
完整寫法是 Object.prototype.toString.call(xxx)
, 就目前來看,這個方法是最好的一個方法來檢測所有的數據類型,無論是基本數據類型還是引用數據類型:
toString方法是Object原型對象上的一個方法,默認返回調用者的具體類型,換句話說,toString運行時this指向的對象類型,返回格式為 [object xxx]
,但是需要注意的是,有時候我們創建一個對象的時候可能會重寫這個方法,這樣就可能會導致Object的toString執行不到,所以這里需要用call方法來強制執行Object方法。
4、constructor
constructor
在其對應對象的原型下面,自動生成,當我們寫一個構造函數的時候,會自動添加一個:
構造函數名.prototype.constructor = 構造函數名
function test(){ }
test.prototype.constructor = test; // 這個是自動會生成的
于是就有了:
圖上可以看出來,Null
和 Undefined
是不能夠被判斷出來的,還會報錯,因為 Null
和 Undefined
都是無效的對象,所以不存在 constructor
這一說。另外一點需要注意的是,constructor
屬性是可以被修改的,可能會導致最后的結果不正確。