JavaScript 的數(shù)據(jù)類型檢測是我們平時開發(fā)中經(jīng)常會遇到的場景伤疙,小到基本數(shù)據(jù)類型大至各種引用數(shù)據(jù)類型的檢測乐导,都是我們需要掌握的知識點肯骇。本章會詳細講解 JavaScript 中各種不同數(shù)據(jù)類型的檢測方法以及最后會實現(xiàn)一個數(shù)據(jù)類型檢測的終極方法。
紅寶石書告訴我們碟案,JavaScript 中的數(shù)據(jù)類型有Undefined愿险、Null、Boolean价说、Number辆亏、String、Object鳖目,其中前五種是基本類型扮叨,而 Object 是引用類型。實際上领迈,Object 中還包含了其它更為具體的引用類型彻磁,如Array、Function狸捅、Date衷蜓、RegExp、Error尘喝、Arguments等磁浇。
在本章的敘述中,我都會以上述 12 種數(shù)據(jù)類型為基礎來說明不同的檢測方式(實際上 JavaScript 中數(shù)據(jù)類型不止 12 種瞧省,其它數(shù)據(jù)類型我們鮮少碰到扯夭,所以在此就不多做贅述啦)鳍贾。
我們通常用來檢測數(shù)據(jù)類型的方法鞍匾,分別是typeof和Object.prototype.toString,讓我們仔細來看看這兩個方法骑科。
typeof
MDN 中的敘述是橡淑,typeof 操作符返回一個字符串,表示未經(jīng)計算的操作數(shù)的類型咆爽。
其使用方式是 typeof operand 或 typeof(operand)梁棠,operand?是一個表達式置森,表示對象或原始值,其類型將被返回符糊,返回值是表示其數(shù)據(jù)類型的字符串的小寫形式凫海。
那么讓我們直接來看一下上述的 12 種數(shù)據(jù)類型使用 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 方法來檢測數(shù)據(jù)類型男娄,基本類型大部分都能被準確檢測并返回正確的字符串(除了 Null 類型行贪,其返回 object 字符串),而引用類型大部分都不能夠被準確檢測(除了 Function 類型能夠準確返回 function 字符串外模闲,其它的都返回了 object 字符串)建瘫。
由此可得,typeof 方法并不能夠完全精準地檢測出上述 JavaScript 中的 12 中數(shù)據(jù)類型尸折。
Object.prototype.toString
ES5 規(guī)范中是這么描述 Object.prototype.toString 的:
可以知道啰脚,Object.prototype.toString 最終會返回形式如 [object,class] 的字符串,class 指代的是其檢測出的數(shù)據(jù)類型实夹,這個是我們判斷數(shù)據(jù)類型的關鍵橄浓。
同樣的,讓我們來看下使用 Object.prototype.toString 來檢測上述列舉到的 12 種數(shù)據(jù)類型都會返回什么樣的結(jié)果:
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 準確的表示了各個數(shù)據(jù)的類型,與 typeof 不同的是塞赂,class 所代表的數(shù)據(jù)類型字符串首字母是大寫的泪勒,而不像 typeof 返回的是小寫字符串。
數(shù)據(jù)類型檢測終極方法
通過上述對兩個檢測數(shù)據(jù)類型方法的介紹宴猾,我們知道 typeof 能夠被用來檢測除 Null 類型外的其它基本類型圆存,并且能夠檢測出引用類型中 Function 數(shù)據(jù)類型,而 Object.prototype.toString 能夠檢測出所有的數(shù)據(jù)類型仇哆,所以我們可以結(jié)合這兩個方法來實現(xiàn)一個 JavaScript 數(shù)據(jù)類型檢測的終極方法沦辙。
/** * @desc 數(shù)據(jù)類型檢測 * @param obj 待檢測的數(shù)據(jù) * @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)];}復制代碼
數(shù)據(jù)類型的單獨檢測
有時我們希望直接判斷一個數(shù)據(jù)是否是某個類型,那么我們可以單獨實現(xiàn)這些判斷某個數(shù)據(jù)類型的函數(shù)讹剔,這里直接給出各個函數(shù)的實現(xiàn)代碼油讯,需要的童鞋可以直接使用。
/** * @desc 是否是 Undefined 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisUndefined(obj) {returnobj === void 0;}/** * @desc 是否是 Null 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisNull(obj) {returnobj === null;}/** * @desc 是否是 Boolean 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisBoolean(obj) {returntypeof(obj) ==='boolean';}/** * @desc 是否是 Number 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisNumber(obj) {returntypeof(obj) ==='number';}/** * @desc 是否是 String 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisString(obj) {returntypeof(obj) ==='string';}/** * @desc 是否是 Object 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisObject(obj) {returnObject.prototype.toString.call(obj) ==='[object Object]';}/** * @desc 是否是 Array 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisArray(obj){returnArray.isArray?Array.isArray(obj):Object.prototype.toString.call(obj) ==='[object Array]';}/** * @desc 是否是 Function 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisFunction(obj){returntypeof(obj) ==='function';}/** * @desc 是否是 Date 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisDate(obj){returnObject.prototype.toString.call(obj) ==='[object Date]';}/** * @desc 是否是 RegExp 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisRegExp(obj){returnObject.prototype.toString.call(obj) ==='[object RegExp]';}/** * @desc 是否是 Error 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisError(obj){returnObject.prototype.toString.call(obj) ==='[object Error]';}/** * @desc 是否是 Arguments 類型檢測 * @param obj 待檢測的數(shù)據(jù) * @return{Boolean} 布爾值 */functionisArguments(obj){returnObject.prototype.toString.call(obj) ==='[object Arguments]';}