Javascript类型检测 - 第八基地

软件开发的家园,编程爱好者的天地.

现在是:北京时间 2016/4/14 上午11:50:51 星期四

设为首页  |  加入收藏  |  网站地图

Javascript类型检测
发布于:第八基地 来源:互联网 作者:天堂路上 时间:2011-10-15 点击:128

  开门见山,我们先来看一下代码:

varis=function(obj,type){vartoString=Object.prototype.toString;var_baseTypes={'undefined':'undefined','number':'number','boolean':'boolean','string':'string'};return(_baseTypes[typeofobj]===type)||(type==="Null"&&obj===null)||(type==='Function'&&"object"===typeofdocument.getElementById?/^\s*\bfunction\b/.test(""+obj):toString.call(obj).slice(8,-1)===type)||objinstanceoftype;};

  在讲解这个函数之前,让我们先来看一下javascript类型判断的几个关键:

  typeof

  typeof运算符,用于判断一个或值是哪种类型的。

  由于Javascript语言的灵性性与执行环境的复杂性,typeof运算符并不能正确判断出所有的类型。但对于基本数据类型,typeof具有神奇的功效,正如在is函数中看到的那样,_baseTypes变量中定义了typeof可以正确识别的基本数据类型列表,其中键为类型名称,值为typeof运算结果。

  instanceof

  ?????instanceof可以检测某个对象是不是另一个对象的实例。

newString('abc')instanceofString//true

  instanceof还可以检测父类型。 

functionAnimal(){};functionPig(){};Pig.prototype=newAnimal();alert(newPig()instanceofAnimal);//true

  可以看出,instanceof不适合用来检测一个对象本身的类型。

  Constructor

  所有对象都拥有一个constructor属性,它指向该对象的构造函数。对于复合数据类型,我们可以采用如下方式进行检测:

isArray:function(arr){return!!arr&&arr.constructor==Array;}

  但是比较悲剧的是这种行为并不是确定的,在一些极其特殊的情况下,会产生意外的结果:

variframe=document.createElement('iframe');document.body.appendChild(iframe);varxArray=window.frames[window.frames.length-1].Array;vararr=newxArray(1,2,3);//[1,2,3]alert(arrinstanceofArray);//false

  下面是JohgResig《projavacriptTechniques》书中的一张列表:

  DuckTyping 

  在犀牛书里,提到一句老话:"如果走路像鸭子,叫声像鸭子,那他就是鸭子"。换而言之,对于Array来说,如果一个对象有splice和join属性,那它就是一个Array:

functionisArray(o){returno!=null&&typeofo===‘object’&&'splice'ino&&'join'ino;}

  显然,鸭子检测很容易误把自造的天鹅也当成鸭子:

alert(isArray({'splice':'','join':''}));//true

  注:bucktyping并不关注于类型,它关注的是行为,它是实际作用是相互之间约定一种行为接口,好实现类似于多态的调用

  Object.toString?

   ECMA-262中的解释:

  Object.prototype.toString()

  whenthetoStringmethodiscalled,thefollowingstepsaretaken:

  1.getthe[[Class]]propertyofthisobject //得到内部属性[[Class]]

  2.conputeastringvaluebyconcatenatingthethreestrings"[object",Result(1),and"]"//构造一个字符串类型似于[objectxxx]

  3.returnresults(2)//返回第2条的执行结果

  注:[[Class]]为对象的内部属性,无法真接访问到,这样,就有了:

functionisArray(o){returnObject.prototype.toString.call(o)==='[objectArray]';}

  因为是字符串比较,也就解决了环境问题和语法灵活性所带来的变化,因此比较稳定。好,讲到现在,想必大家对javascript类型判断应该有一个较为深入的理解,我想通过自已的能力,应该也可以写一个比较完善的类型判断函数,那下面就来看一下我是如何实现的。

varis=function(obj,type){vartoString=Object.prototype.toString;var_baseTypes={'undefined':'undefined','number':'number','boolean':'boolean','string':'string'};return(_baseTypes[typeofobj]===type)||(type==="Null"&&obj===null)||(type==='Function'&&"object"===typeofdocument.getElementById?/^\s*\bfunction\b/.test(""+obj):toString.call(obj).slice(8,-1)===type)||objinstanceoftype;};

  因为考虑到实用性,这里是通过传入对象obj和期望类型type,返回boolean值,true为obj为type类型,false为obj不为type类型来实现的。首先,??vartoString =Object.prototype.toString;这里保存了一份对Object的原生toString方法的引用,方便后面使用:

???var_baseTypes={'undefined':'undefined','number':'number','boolean':'boolean','string':'string'};

  这里保存了一份对于typeof可以检测出来的基本数据类型的对象列表,其键类型名称,值为typeof该类型的结果。然后:进行类型的检测,返回结果。

  (_baseTypes[typeofobj]===type):检测是否为基本数据类型

  (type==='Null'&&obj===null):因为null实际上属于Object类型,因此typeofnull和Object.prototype.toString(null)返回的结果都为object和[Objectobject]

  在实际需求中,我们通常希望将null单独列出来作为一种类型来进行判断:

(type==='function'&&'object'===typeofdocument.getElementById?/^\s*\bfunction\b/.test(""+obj):toString.call(obj).slice(8,-1)===type)
对我有帮助
(0)
0%
对我没帮助
(0)
0%
返回顶部
在线反馈
在线反馈