型別判斷是個常見問題,有多種不同的判斷方式,每種方式都有適用的場景。
typeof
typeof
操作符返回一個字串,表示未經計算的運算元的型別。
typeof operand
或者 typeof (operand)
都可以,括號為可選的。
型別 | 結果 |
---|---|
Undefined | “undefined” |
==Null== | ==”object”== |
Boolean | “boolean” |
Number | “number” |
String | “string” |
Symbol(ECMAScript 6 新增) | “symbol” |
==函式物件== | ==”function”== |
任何其他物件 | “object” |
typeof 會將 null
和 Object
都返回為 “object”, 這樣就無法區分具體的物件型別(Array , Date , Error等)。
注意:其中函式物件特別返回為”function” 。
// `number`
typeof 1
typeof NaN
typeof Infinity
// `string`
typeof `1`
// `boolean`
typeof true
// `undefined`
typeof undefined
// `symbol`
typeof Symbol(1)
// `object`
typeof null
// `object`
typeof {}
typeof []
typeof new Date()
typeof new Number(1)
// `function`
typeof function(){}
typeof class A {}
typeof Math.sin
instanceof
instanceof運算子用於測試建構函式的prototype屬性是否出現在==物件==的原型鏈中的任何位置
object instanceof constructor
- 左側引數如果不是物件,將返回false
- 右側引數如果不是建構函式,將報錯
let x = 1;
let y = new Number(1);
x instanceof Number // false 1 不是物件
y instanceof Number // true new Number(1)為物件
// 雖然這種方式測試“x”有原型,但是應該是在獲取的時候,自動進行了物件包裝, 其實獲取的是 new Number(1)
x.__proto__ === Object.getPrototypeOf(x) === Number.prototype
// 沿著原型鏈比對 y.__proto__.__proto__ === Object.prototype , 故返回true
y instanceof Object // true
instanceof 的判斷結果會隨著物件或者建構函式的改變而不同,而不是固定的值
class A {}
class B {}
let a = new A();
a instanceof A // true
a instanceof B // false
// 修改a的 __proto__ 指向
a.__proto__ = B.prototype
a instanceof A // false
a instanceof B // true
instanceof不能判斷原始資料型別,但是可以用來判斷物件具體是那種型別
[] instanceof Array // true
new Error() instanceof Error // true
(/[1-9]+/) instanceof RegExp // ture
new Date() instanceof Date // true
let x = document.querySelectorAll(`h1`)
x instanceof NodeList // true
···
Object.prototype.toString()
toString()
方法返回一個表示該物件的字串。預設情況下,toString()
方法被每個Object物件繼承。如果此方法在自定義物件中未被覆蓋,toString()
返回 “[object type]” ,其中type是物件的型別。
待檢測物件也許會重寫toString()
方法,這時就無法檢測toString
來判斷型別。所以要保證能夠檢測型別,需要呼叫Object.prototype.toString
來進行判斷。如下:
let X = function(x) {
this.name = x
}
let x = new X();
x.toString() // "[object,Object]" 使用繼承的toString
Object.prototype.toString.call(x) // "[object,Object]"
X.prototype.toString = function() { // 重寫父類的toString方法
return `not type`
}
x.toString() // "not type" 使用重寫後的toString , 就不再返回型別
Object.prototype.toString.call(x) // "[object,Object]"
返回的” [ object, Type]” 不好分辨,可以進行特殊的處理,直接返回型別名稱。
// 獲取型別
function getType(target){
let types = {}
let temp = Object.prototype.toString.call(target)
//types對映型別
`Boolean Number String Null Undefined Symbol Function Array Date RegExp Object Error NodeList`.split(` `).map(value => {
types[`[object ${value}]`] = value.toLowerCase()
})
if (types[temp]) {
return types[temp]
}else if (temp.indexOf(`HTML`) !== -1) { // 判斷是否為DOM元素
return `element`
}else {
return
}
}
// 測試
getType(1) // "number"
getType(Symbol(1)) // "symbol"
getType([]) // "array"
getType({}) // "object"
getType(document.querySelectorAll(`div`)) // "nodelist"
用如上方法,就可以便捷的獲取到型別名稱了。
其他API
判斷值是否是 NaN Number.isNaN()
Number.isNaN()
判斷值是否是 NaN,和全域性函式 isNaN() 相比,該方法不會強制將引數轉換成數字,只有在引數是真正的數字型別,且值為 NaN 的時候才會返回 true。
Number.isNaN(NaN); // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0) // true
Number.isNaN(null); // false
Number.isNaN(37); // false
Number.isNaN("37"); // false
Number.isNaN("NaN"); // false 不會隱式轉換
window.isNaN(`NaN`) // true 會隱式轉換
判斷值是否為有窮數 Number.isFinite()
Number.isFinite()
方法用來檢測傳入的引數是否是一個有窮數(finite number)。 和全域性的 isFinite() 函式相比,這個方法不會強制將一個非數值的引數轉換成數值,這就意味著,只有數值型別的值,且是有窮的(finite),才返回 true
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Number.isFinite(-Infinity); // false
Number.isFinite(0); // true
Number.isFinite(2e64); // true
Number.isFinite(`0`); // false, 全域性函式 isFinite(`0`) 會返回 true
判斷值是否為整數 Number.isInteger()
Number.isInteger()
方法用來判斷給定的引數是否為整數。
Number.isInteger(0); // true
Number.isInteger(1); // true
Number.isInteger(-100000); // true
Number.isInteger(0.1); // false
Number.isInteger(Math.PI); // false
Number.isInteger(Infinity); // false
Number.isInteger(-Infinity); // false
Number.isInteger("10"); // false 不會進行隱式轉換
Number.isInteger(true); // false
Number.isInteger(false); // false
Number.isInteger([1]); // false