JS數(shù)據(jù)類型判斷的9種方式總結
前言
JS 的數(shù)據(jù)類型檢測是一道經(jīng)典的八股文面試題。相信大家都能條件反射的回答出 4 種方法:typeof、constructor、instanceof 和 Object.prototype.toString,并且對它們各自的優(yōu)缺點也是張口就來。
本文對這些方法做了簡單歸納,同時又補充了其他 5 種和數(shù)據(jù)類型檢測有關的方法,供諸君食用。
typeof:檢測基礎數(shù)據(jù)類型和函數(shù)很好用
typeof 應該是我學習到的第一個 JS 的方法,也是使用頻率最高的一個用來檢測數(shù)據(jù)類型的方法。
它能準確判斷出的數(shù)據(jù)類型有:Number,String,Boolean,Undefined,Symbol,BigInt,F(xiàn)unction。
它的缺點就是不能準確判斷 null 的類型,而是返回 “object”。對于數(shù)組,日期,普通對象等數(shù)據(jù),統(tǒng)一返回 “object”。
所以在判斷基本數(shù)據(jù)類型(除了 null)和函數(shù)類型時,都會使用它。
constructor:返回實例對象的構造函數(shù)
學習 JS 到面向對象的階段時,會學到 JS 的原型鏈和原型對象,會學到通過 new 一個構造函數(shù),來創(chuàng)建實例對象。
構造函數(shù)的原型對象上會有一個 constructor 屬性,指向了構造函數(shù)自身,所以實例對象通過原型鏈訪問 constructor 屬性,就能找到自己的構造函數(shù),也就是自己的類型了。
它的本意是用來標識自己的構造函數(shù),卻臨時拉來當壯丁,用來判斷數(shù)據(jù)類型,當然也存在一定的風險:
- null,undefined 沒有構造函數(shù),自然也就訪問不到該屬性,因此不能使用此屬性來判斷
- constructor 可以被改寫,所以不一定準確
來看幾個例子:
console.log((1).constructor === Number) // true ? console.log([1, 2, 3].constructor === Array) // true ? console.log(undefined.constructor === Array) // 報錯
在平時寫代碼時,基本上不會用它來做數(shù)據(jù)類型的檢測。
instanceof:沿著原型鏈去找
它和 constructor 一樣,也是臨時拉來當壯丁。它的作用是檢測實例對象是不是屬于某個構造函數(shù),可以用來做數(shù)據(jù)類型的檢測。
術業(yè)有專攻,所以它也有缺點:
- 不能檢測基本數(shù)據(jù)類型
- 原型鏈可能被修改,導致檢測結果不準確
- 只要能在原型鏈上找到構造函數(shù),就返回 true,所以類型可能不準確
來看幾個例子:
console.log(1 instanceof Number) // false ? console.log([] instanceof Array) // true ? console.log([] instanceof Object) // true
實際中 instanceof 也很少用。
Object.prototype.toString:是個大拿
看名字它是用來將一個值轉為字符串的,但其實并不是,它是一個專門檢測數(shù)據(jù)類型的方法。
它返回的值是一個形如 [object Object] 的字符串,比如:
console.log(toString.call('123')) // [object String]
console.log(toString.call(null)) // [object Null]
console.log(toString.call(true)) // [object Boolean]
console.log(toString.call({})) // [object Object]
console.log(toString.call([])) // [object Array]
console.log(toString.call(function(){})) // [object Function]
console.log(toString.call(new Map)) // [object Map]
console.log(toString.call(new WeakSet)) // [object WeakSet]通常會編寫一個函數(shù),對返回的字符串從第8位做一個截取,截取到倒數(shù)第一位,再去做類型比較。
Symbol.toStringTag:自定義類型
上面的 Object.prototype.toString 方法,之所以對不同的數(shù)據(jù)類型,返回不同的標識字符串,就是因為 Symbol.toStringTag 。
Symbol.toStringTag 是一個內置符號屬性,它的值是一個字符串,用于表示一個對象的默認描述,也就是調用 Object.prototype.toString 會返回的內容,比如:
let obj = {}
obj[Symbol.toStringTag] = 'ABC'
console.log(Object.prototype.toString.call(obj)) // [object ABC]對于自定義對象,調用上面的方法,都只會返回 [object Object]。此時就可以使用 Symbol.toStringTag 來指定一個確定的類型了,比如:
class Person{
get[Symbol.toStringTag](){
return 'Person'
}
}
let person = new Person()
?
console.log(Object.prototype.toString.call(person)) // [object Person]Object.prototype.isPrototypeOf:和 instanceof 類似
isPrototypeOf 和 instanceof 類似,都是基于原型鏈和原型對象去做判斷的。它用來檢查一個對象是否存在于另一個對象的原型鏈上。
function Person() {
}
?
let person = new Person()
?
console.log(Person.prototype.isPrototypeOf(person))Array.isArray:專業(yè)檢測數(shù)組三十年
起初以為它是 ES6 提供的新方法,后來得知其實屬于 ES 5.1 規(guī)范。
看名字就知道,它是專門用于檢測數(shù)組類型的,該方法的命名真實言簡意賅。
Array.isArray([]) // true
Number.isNaN
這個方法就是真的屬于 ES6 標準了。
我們知道,JS 中有一個特殊的“數(shù)字” NaN,表示 not a number,不是一個數(shù)字,但它卻歸屬于數(shù)字類型:
console.log(typeof NaN) // 'number'
NaN 用于表示不是一個數(shù)字,它不等于任何值,包括它本身。在 ES6 之前,windows 對象提供了一個全局方法 isNaN,用于判斷一個數(shù)字是不是 NaN:
isNaN(10) // false
isNaN('abc') // true
isNaN(NaN) // true可以發(fā)現(xiàn),isNaN 對于字符串的檢測結果也是 NaN。但這其實并不嚴謹,它對要判斷的數(shù)據(jù)做了一個隱式類型轉換,先轉為數(shù)字再進行判斷。而NaN 的檢測應該僅限于數(shù)字類型,所以 ES6 提供了 Number.isNaN 方法:
Number.isNaN(NaN) // true
Number.isNaN('123') // false它能判斷一個值是否嚴格等于NaN。
等比較:與固定值進行比較
直接通過與一個特定的值進行比較,從而判斷數(shù)據(jù)的類型,比如:
let value = null console.log(value === null) // true ? // 同時判斷一個值是 undefined 或者 null let value console.log(value == null) // true
總結
本文整理了 JS 中常用的判斷數(shù)據(jù)類型的方法,其中 typeof 和 Object.prototype.toString 使用場景是最多的,對一些特殊的數(shù)據(jù)類型,比如 null,NaN,自定義類型,可以選擇其他的方式去進行判斷,做到靈活運用。
到此這篇關于JS數(shù)據(jù)類型判斷的9種方式的文章就介紹到這了,更多相關JS數(shù)據(jù)類型判斷內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
ES6中Proxy與Reflect實現(xiàn)重載(overload)的方法
這篇文章主要介紹了ES6中Proxy與Reflect實現(xiàn)重載(overload)的方法,分析了重載的原理及使用Proxy和Reflect來實現(xiàn)重載的操作步驟與相關技巧,需要的朋友可以參考下2017-03-03

