JavaScript 數據類型檢測終極解決方案

JavaScript 的數據類型檢測是我們平時開發中經常會遇到的場景,小到基本數據類型大至各種引用數據類型的檢測,都是我們需要掌握的知識點。本章會詳細講解 JavaScript 中各種不同數據類型的檢測方法以及最后會實現一個數據類型檢測的終極方法。

紅寶石書告訴我們,JavaScript 中的數據類型有Undefined、Null、Boolean、Number、String、Object,其中前五種是基本類型,而 Object 是引用類型。實際上,Object 中還包含了其它更為具體的引用類型,如Array、Function、Date、RegExp、Error、Arguments等。

在本章的敘述中,我都會以上述 12 種數據類型為基礎來說明不同的檢測方式(實際上 JavaScript 中數據類型不止 12 種,其它數據類型我們鮮少碰到,所以在此就不多做贅述啦)。

我們通常用來檢測數據類型的方法,分別是typeofObject.prototype.toString,讓我們仔細來看看這兩個方法。

typeof

MDN 中的敘述是,typeof 操作符返回一個字符串,表示未經計算的操作數的類型。

其使用方式是 typeof operand 或 typeof(operand),operand?是一個表達式,表示對象或原始值,其類型將被返回,返回值是表示其數據類型的字符串的小寫形式。

那么讓我們直接來看一下上述的 12 種數據類型使用 typeof 來檢測后返回值分別是什么:

var und=undefined;var nul=null;var boo=true;var num=1;var str='xys'var obj=new Object();var arr=[1,2,3];var fun=function(){}var date=new Date();var reg = /a/g;var err=new Error()var arg;(functiongetArg(){? ? arg=arguments;})();console.log(typeof und);? // undefinedconsole.log(typeof nul);? // objectconsole.log(typeof boo);? // booleanconsole.log(typeof num);? // numberconsole.log(typeof str);? // stringconsole.log(typeof obj);? // objectconsole.log(typeof arr);? // objectconsole.log(typeof fun);? //functionconsole.log(typeof date);? // objectconsole.log(typeof reg);? // objectconsole.log(typeof err);? // objectconsole.log(typeof arg);? // object復制代碼

可以看到,使用 typeof 方法來檢測數據類型,基本類型大部分都能被準確檢測并返回正確的字符串(除了 Null 類型,其返回 object 字符串),而引用類型大部分都不能夠被準確檢測(除了 Function 類型能夠準確返回 function 字符串外,其它的都返回了 object 字符串)。

由此可得,typeof 方法并不能夠完全精準地檢測出上述 JavaScript 中的 12 中數據類型。

Object.prototype.toString

ES5 規范中是這么描述 Object.prototype.toString 的:


可以知道,Object.prototype.toString 最終會返回形式如 [object,class] 的字符串,class 指代的是其檢測出的數據類型,這個是我們判斷數據類型的關鍵。

同樣的,讓我們來看下使用 Object.prototype.toString 來檢測上述列舉到的 12 種數據類型都會返回什么樣的結果:

var toString=Object.prototype.toString;console.log(toString.call(und));? // [object Undefined]console.log(toString.call(nul));? // [object Null]console.log(toString.call(boo));? // [object Boolean]console.log(toString.call(num));? // [object Number]console.log(toString.call(str));? // [object String]console.log(toString.call(obj));? // [object Object]console.log(toString.call(arr));? // [object Array]console.log(toString.call(fun));? // [object Function]console.log(toString.call(date));? // [object Date]console.log(toString.call(reg));? // [object RegExp]console.log(toString.call(err));? // [object Error]console.log(toString.call(arg));? // [object Arguments]復制代碼

可以看到,Object.prototype.toString 返回的 [object,class] 字符串中,class 準確的表示了各個數據的類型,與 typeof 不同的是,class 所代表的數據類型字符串首字母是大寫的,而不像 typeof 返回的是小寫字符串。

數據類型檢測終極方法

通過上述對兩個檢測數據類型方法的介紹,我們知道 typeof 能夠被用來檢測除 Null 類型外的其它基本類型,并且能夠檢測出引用類型中 Function 數據類型,而 Object.prototype.toString 能夠檢測出所有的數據類型,所以我們可以結合這兩個方法來實現一個 JavaScript 數據類型檢測的終極方法。

/** * @desc 數據類型檢測 * @param obj 待檢測的數據 * @return{String} 類型字符串 */functiontype(obj) {? ? var toString=Object.prototype.toString;? ? var toType = {};? ? vartypeArr=['Undefined','Null','Boolean','Number','String','Object','Array','Function','Date','RegExp','Error','Arguments']typeArr.map(function(item, index) {? ? ? ? toType["[object "+ item +"]"] = item.toLowerCase();? ? })returntypeof obj !=="object"? typeof obj : toType[toString.call(obj)];}復制代碼

數據類型的單獨檢測

有時我們希望直接判斷一個數據是否是某個類型,那么我們可以單獨實現這些判斷某個數據類型的函數,這里直接給出各個函數的實現代碼,需要的童鞋可以直接使用。

/** * @desc 是否是 Undefined 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisUndefined(obj) {returnobj === void 0;}/** * @desc 是否是 Null 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisNull(obj) {returnobj === null;}/** * @desc 是否是 Boolean 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisBoolean(obj) {returntypeof(obj) ==='boolean';}/** * @desc 是否是 Number 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisNumber(obj) {returntypeof(obj) ==='number';}/** * @desc 是否是 String 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisString(obj) {returntypeof(obj) ==='string';}/** * @desc 是否是 Object 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisObject(obj) {returnObject.prototype.toString.call(obj) ==='[object Object]';}/** * @desc 是否是 Array 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisArray(obj){returnArray.isArray?Array.isArray(obj):Object.prototype.toString.call(obj) ==='[object Array]';}/** * @desc 是否是 Function 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisFunction(obj){returntypeof(obj) ==='function';}/** * @desc 是否是 Date 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisDate(obj){returnObject.prototype.toString.call(obj) ==='[object Date]';}/** * @desc 是否是 RegExp 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisRegExp(obj){returnObject.prototype.toString.call(obj) ==='[object RegExp]';}/** * @desc 是否是 Error 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisError(obj){returnObject.prototype.toString.call(obj) ==='[object Error]';}/** * @desc 是否是 Arguments 類型檢測 * @param obj 待檢測的數據 * @return{Boolean} 布爾值 */functionisArguments(obj){returnObject.prototype.toString.call(obj) ==='[object Arguments]';}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容