Object.prototype.toString应用和原理探析

Posted 程序猿子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Object.prototype.toString应用和原理探析相关的知识,希望对你有一定的参考价值。

查阅各种资料,在javascript语言中为了准确判断对象的数据类型也是拼了,各种或土法或高大上法齐上阵也未必能得到预期的结果,这篇博客来做一个简单的总结。

一 typeof运算符的使用和局限

实际用例最能说明问题,测试之:
console.info("typeof  undefined : ", typeof  undefined);
console.info("typeof  null : ", typeof  null);
console.info("typeof  NaN : ", typeof  NaN);
console.info("typeof  true : ", typeof  true);
console.info("typeof  3.65 : ", typeof  3.65);
console.info('typeof  "weather" : ', typeof  "weather");
console.info("typeof   : ", typeof  );
console.info("typeof  [] : ", typeof  []);
console.info("typeof  function() : ", typeof  function());
console.info("typeof  new Object() : ", typeof  new Object());
console.info("typeof  new Array() : ", typeof  new Array());
console.info("typeof  new RegExp() : ", typeof  new RegExp());
结果如下:
typeof  undefined :  undefined
typeof  null :  object
typeof  NaN :  number
typeof  true :  boolean
typeof  3.65 :  number
typeof  "weather" :  string
typeof   :  object
typeof  [] :  object
typeof  function() :  function
typeof  new Object() :  object
typeof  new Array() :  object
typeof  new RegExp() :  object
可以看到typeof运算符的特征是:
undefined就是一种独立的名为undefined类型。
null是object类型的。
对象和数组均为object类型的。
函数有专门的function类型。
但是没有专门的array类型,对数组使用typeof运算符返回的还是'object',即typeof无法区分Object和Array。这还不是最要命的,最要命的是typeof运算符也无法区分其他内建对象类型,对于Object/Math/RegExp它都认为反正都是'object'类型。

二 instanceof和constructor的使用和局限

再对instanceof运算符测试:
console.info("new Boolean(true) instanceof Boolean : ", new Boolean(true) instanceof Boolean);
console.info('new String("abc") instanceof String : ', new String("abc") instanceof String);
console.info("new Number(3.1415) instanceof Number : ", new Number(3.1415) instanceof Number);
console.info(" instanceof Object : ",  instanceof Object);
console.info("[] instanceof Object : ", [] instanceof Object);
console.info("new Array() instanceof Array : ", new Array() instanceof Array);
console.info("(function()) instanceof Object : ", (function()) instanceof Object);
console.info("new Function('return;') instanceof Function : ", new Function('return;') instanceof Function);
console.info('new RegExp("\\\\d+") instanceof Object : ', new RegExp("\\\\d+") instanceof Object);
console.info('new RegExp("\\\\d+") instanceof RegExp : ', new RegExp("\\\\d+") instanceof RegExp);
结果全部为true,说明instanceof运算符符合预期的行为,即可以准确判断给定所有内建对象的实际类型和父类型。constructor属性类似,任何具备这个属性的对象都可以返回其对应构造函数。
instanceof运算符的局限是用来做类型通用判断时需要给定运算符右边一个构造函数名,对未知构造函数构造的对象来说无法提前给定,constructor属性返回的值又不是预期的单纯的构造函数名。
instanceof运算符还有一个局限,就是无法支持基本数据类型的类型判断,比如下面第一行会抛异常,其他的测试结果全部是false。
console.info('undefined instanceof undefined : ', undefined instanceof undefined);
console.info('null instanceof Object : ', null instanceof Object);
console.info('true instanceof Boolean : ', true instanceof Boolean);
console.info('"abc" instanceof String : ', "abc" instanceof String);
console.info('3.1415 instanceof Number : ', 3.1415 instanceof Number);
console.info('Boolean(true) instanceof Boolean : ', Boolean(true) instanceof Boolean);
console.info('String("abc") instanceof String : ', String("abc") instanceof String);
console.info('Number(3.1415) instanceof Number : ', Number(3.1415) instanceof Number);

三 Object.prototype.toString的使用和局限

听说Object.prototype.toString很强大,继续测试之:
function Circle(x,y,r) 
	this.x=x;
	this.y=y;
	this.r=r;


function Rectangle(x,y,width,height) 
	this.x=x;
	this.y=y;
	this.width=width;
	this.height=height;


console.info(Object.prototype.toString.call());
console.info(Object.prototype.toString.call(Math));
console.info(Object.prototype.toString.call(new RegExp("\\\\d+")));
console.info(Object.prototype.toString.call(new Circle(1,1,1)));
console.info(Object.prototype.toString.call(new Rectangle(1,1,4,3)));
结果如下:
[object Object]
[object Math]
[object RegExp]
[object Object]
[object Object]
说明Object.prototype.toString对所有的内建对象都能支持得非常好,经测试对客户端对象也可以支持得非常好,唯独遗憾的是对用户自定义类型无法区分,但是作为常见的判断内建类型对象和客户端类型对象已经足够使用了,进一步的测试带来更大的惊喜:该方法对基本类型也支持得非常好,测试以下语句输出:
console.info(Object.prototype.toString.call(undefined));
console.info(Object.prototype.toString.call(null));
console.info(Object.prototype.toString.call(3.1415));
console.info(Object.prototype.toString.call(true));
console.info(Object.prototype.toString.call(""));
作为通用的判断所有数据(基本类型和对象类型)类型的方法,稍微调整一下以便该方法对基本类型数据的行为与typeof保持一致(对null的处理不一致,但是显然这里更符合预期)且能对非用户自定义对象类型输出精确类型描述:
function type(o) 
	var show = Object.prototype.toString.call(o);
	return show.substring(8,show.length - 1).toLowerCase();

四 jQuery对对象的识别

搜集整理下jQuery1.6.1版本中关于对象识别的代码:
	// [[Class]] -> type pairs
	class2type = ;

	// Populate the class2type map
	jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) 
		class2type[ "[object " + name + "]" ] = name.toLowerCase();
	);
	
	jQuery.type: function( obj ) 
			return obj == null ?
				String( obj ) :
				class2type[ toString.call(obj) ] || "object";
		,

由此可见这个版本(1.6.1)用于对象类型的判定方法并不高级,不知道最新的2.x版本内部实现如何。





以上是关于Object.prototype.toString应用和原理探析的主要内容,如果未能解决你的问题,请参考以下文章

Object.prototype.toString.call()方法

Object----Object.prototype.toString.call()方法的使用

Object.prototype.valueOf()和Object.prototype.toString()

Object.prototype.toString.call()方法

js变量类型判断 严格通用 Object.prototype.toString.call()

从toString()方法到Object.prototype.toString.call()方法