判断JS中的数据类型,通过typeof 和object对象的tostring方法获取
2016-12-13 01:07

jquery中有一个方法,$.type(obj)来检测数据类型,用过的前端都应该知道,他能准确的返回一个对象的类型的字符串形式。

今天我们就来分析一下jquery这个方法的实现原理。可能你会说,既然jquery已经提供了这么好的方法了,我们拿来直接用不就得了。确实,拿来主义省事又省事;但如果一直这样的话,你的js水平只能是依赖中jquery的基础上,离开了jquery你什么也干不了了。这并不可怕,现在我们的项目中都在用jquery,甚至移动端我们还有zepto可以替代jquery使用。

  现时,已经有好多新兴的前端框架出来了(如angular,react等),他们都可以不依赖jquery,因为他们内部封装了简单jquery库,所谓简单,就是一些常用的功能。而像一些不常用的就抛弃了。这个时候你如果仅仅为了判断一个数据类型而要再引入一个jquery库,就显得有些劳师动众了。而且学习这些原生js的特性,更能提高我们对js的运行机制的了解。

  不多说了,开始我们的正题。我们大家都知道的判断js中一个对象的数据类型可以用typeof,是的,没错,他确实有这个能力,但是效果如何呢,我们先定义几个对象。

var num=13;//数字类型
var str="mooshine";//字符串类型
var date=new Date();//日期类型
var bool=true//boolean类型
var obj={name:"jstype"};//对象类型
var unde=undefined;//undefined类型
var arr=[];//数组类型
var fun=function fn(){return "love";};//函数类型
var reg=/^\d+\w$/;//正则表达式对象
var err=new Error(100,"error is occurs");//错误类型
var win=window;//window对象
var div=document.getElementById("div");//dom对象

下面我们采用typeof方法来判断这几个对象的类型。

这里只提供了chrome的截图,中IE和firefox下的运行结果是一致的(已亲测),其他截图就不贴了。

通过运行结果,我们可以看出,typeof可以区分基本类型和函数类型以及undefined,至于date类型,err类型,dom类型,以及null类型和数组,正则类型的都返回的是object,这个我们就无法区分他们到底是什么类型了。

当然还有一个方法是instanceof 来判断一个对象是不是属于某一个类型(date instanceof Date),这样是可以的,可毕竟要做很多的判断,看起来就麻烦。

这个截图是js文档中对于tostring方法的介绍,默认也就是objcet根对象。({}此即使object对象),可以看出object对象可以返回object+具体的类型名称。

那么我们应该怎么让array对象或者Date对象调用object对象的tostring方法呢?

js中有两个方法,一个是call,一个是apply用于改变对象中的this指针。我们把object中的this指针改变为array或者Date对象不就可以了么。

从js文档中对这两个方法的介绍中,我们可以看出这两个方法的功能类似,只是传递参数的方法不同,这里我们的用法不用传递参数,所以,这两个方法都可以用。

var obj={};
var tostring=obj.toString;
console.log("number:"+tostring.apply(num));
console.log("string:"+tostring.apply(str));
console.log("date:"+tostring.apply(date));
console.log("boolean:"+tostring.apply(bool));
console.log("obj:"+tostring.apply(obj));
console.log("undefined:"+tostring.apply(unde));
console.log("function:"+tostring.apply(fun));
console.log("err:"+tostring.apply(err));
console.log("window:"+tostring.apply(window));
console.log("dom:"+tostring.apply(dm));
console.log("array:"+tostring.apply(arr));
console.log("null:"+tostring.apply(null));

运行结果如下:

IE8-的运行结果

IE9+,Chrome,Firefox的结果。

可以看到通过object对象的toString方法的可以得到date对象,error对象,array对象不同的字符串,IE8一下不能区分dom,window和null对象。IE9+等现代浏览器连这些对象都可以区分。但是呢,他们返回的形式不是我们想要的[object Array]其中只有Array是我们想要的,而且对比typeof方法,首字母应该缩写,所以我们要对返回结果进行一些处理。

这里参照jquery的方法,进行一些简写

var typearr="Boolean Number String Function Array Date RegExp Object Error".split(" ");
var typeobj={};
var tostring=typeobj.toString;
for(var i=0;i<typearr.length;i++){
	typeobj["[object "+typearr[i]+"]"]=typearr[i].toLowerCase();
}
function type(obj){
	return typeobj[tostring.apply(obj)];
}

运行结果如下:

IE8-中的null,undefined是object,因为IE8-的undefined也是object对象。到这里我们基本能得到我们想要的了,能区分date,array,error等类型。

最后我们看一下jquery的处理方法

function type( obj ) {
	if ( obj == null ) {
		return obj + "";
	}
	return typeof obj === "object" || typeof obj === "function" ?
	class2type[ toString.call(obj) ] || "object" :
	typeof obj;
}

通过加上这些判断运行结果:

加上了null的判断,我们还能区分出undefined和null对象,这样我们除了window和dom对象外,我们都能区分。而dom对象也不用这样区分,他有nodeType,nodeName等区分。而jquery代码中的return中的三元表达式是因为typeof比tostring方法运行快,可想而知,tostring方法毕竟还多了一个apply的处理过程。

最后我们把整个判断数据类型的方法整理成一个完整的方法。

(function(_){//使用闭包形式,避免全局变量的污染和变来那个冲突
    var typearr="Boolean Number String Function Array Date RegExp Object Error".split(" ");
	var typeobj={};
	var tostring=typeobj.toString;
	for(var i=0;i<typearr.length;i++){
	 typeobj["[object "+typearr[i]+"]"]=typearr[i].toLowerCase();
	}
	function type(obj){
		if ( obj == null ) {
			return obj + "";
		}
	    return typeof obj === "object" || typeof obj === "function" ?
		typeobj[ toString.call(obj) ] || "object" :
		typeof obj;
	}
       _.getType=type;//将类型判断方法添加到window全局对象上。
 }(window));
 var typename=getType(obj);//调用方式

很简短很简单的一个方法我们就能很轻松的判断数据的准确类型了,而且把这个弄明白的同时,你还顺便学习或者复习了call,apply,tostring等方法。

原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(2878)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1