对于JavaScript中的8种数据类型,并没有直接全面的内置方法来检查数据类型。目前已知的typeof和instanceof无法完美解决问题。本文将介绍如何使用Object.prototype.toString来完美解决这个问题。首先,让我们看看typeof和instanceof的缺点。typeof运算符typeof运算符可能是首先想到的。它适用于数字、字符串、未定义、布尔值、符号、函数,但是在使用typeof时需要注意一些陷阱:1.typeofnull==='object'是一个已知的错误。null不应该是对象类型。2.除了功能外,无法区分普通对象和其他内置对象,如下例所示。类型[];//'对象'typeof{};//'object'typeofnewDate();//'对象'typeof/foo/;//'object'instanceof运算符instanceof运算符检查对象函数的构造以确定它是什么类型,如下例所示。letCar=function(){};letbenz=newCar();benzinstanceofCar;//true因此,instanceof虽然可以正确判断对象的类型,但是无法判断基本类型,如下例所示。[]instanceof数组//?true(()=>{})instanceof函数;//?truenewMap()instanceofMap;//?true1instanceof数字;//?false'foo'instanceofString;//?false另外,由于instanceof是通过检查对象的构造函数来判断类型的,如果在运行时修改了对象的原型,instanceof检查的结果可能会发生变化:constarray=[];arrayinstanceofArray;//?trueObject.setPrototypeOf(array,null);arrayinstanceofArray;//?false如你所见,typeof和instanceof都不是完美的,大多数时候人们不得不结合这两种方法来进行类型检查。Object.prototype.toString方法事实证明,在JavaScript中有第三种更好的方法来检查数据类型——Object.prototype.toString。它是Object.prototype上的一个方法,结果返回一个用于描述对象的字符串值,如下例所示:Object.prototype.toString.call({});//"[objectObject]"Object.prototype.toString.call(1);//"[对象编号]"Object.prototype.toString.call('1');//"[对象字符串]"Object.prototype.toString.call(true);//"[objectBoolean]"Object.prototype.toString.call(newString('string'));//"[对象字符串]"Object.prototype.toString.call(function(){});//"[对象函数]"Object.prototype.toString.call(null);//[objectNull]"Object.prototype.toString.call(undefined);//[对象未定义]"Object.prototype.toString.call(/123/g);//[objectRegExp]"Object.prototype.toString.call(newDate());//[对象日期]"Object.prototype.toString.call([]);//[对象对象数组]"Object.prototype.toString.call(document);//[objectHTMLDocument]"Object.prototype.toString.call(window);//[objectWindow]可以使用regexp返回字符串做一些处理,封装一个通用的方法,适用于所有类型:functiongetType(obj){constlowerCaseTheFirstLetter=(str)=>str[0].toLowerCase()+str.slice(1);//如果是基本数据类型,直接使用typeOf运算符consttype=typeofobj;if(type!=='object'){返回类型;}//对于对象类型使用Object.prototype.toString方法returnlowerCaseTheFirstLetter(Object.prototype.toString.call(obj).replace(/^\[object(\S+)\]$/,'$1'));}获取类型([]);//“数组”getType('123');//"字符串"getType(null);//“空”getType(undefined);//“未定义”getType();//“未定义”getType(function(){});//“函数”getType(/123/g);//"正则表达式"getType(newDate());//“日期”getType(newMap());//"地图"getType(newSet());//"set"可以通过Object.prototype.toString应用于所有数据类型。这也是大多数框架和库中常用的方法。
