开门见山,我们先来看一下代码:
var is = function (obj,type) {
var toString = Object.prototype.toString;
var _baseTypes = { ' undefined ' : ' undefined ' , ' number ' : ' number ' , ' boolean ' : ' boolean ' , ' string ' : ' string ' };
return (_baseTypes[ typeof obj] === type) ||
(type === " Null " && obj === null ) ||
(type === ' Function ' && " object " === typeof document.getElementById ?
/ ^\s*\bfunction\b / .test( "" + obj):toString.call(obj).slice( 8 , - 1 ) === type) ||
obj instanceof type;
};
在讲解这个函数之前,让我们先来看一下javascript类型判断的几个关键:
typeof
typeof运算符,用于判断一个或值是哪种类型的。
由于Javascript语言的灵性性与执行环境的复杂性,typeof运算符并不能正确判断出所有的类型。但对于基本数据类型,typeof具有神奇的功效,正如在 is 函数中看到的那样,_baseTypes变量中定义了typeof可以正确识别的基本数据类型列表,其中键为类型名称,值为typeof运算结果。
instanceof
instanceof可以检测某个对象是不是另一个对象的实例。
new String( ' abc ' ) instanceof String // true
instanceof还可以检测父类型。
function Animal() {};
function Pig() {};
Pig.prototype = new Animal();
alert( new Pig() instanceof Animal); // true
可以看出,instanceof不适合用来检测一个对象本身的类型。
Constructor
所有对象都拥有一个constructor属性,它指向该对象的构造函数。对于复合数据类型,我们可以采用如下方式进行检测:
isArray: function (arr) {
return !! arr && arr.constructor == Array;
}
但是比较悲剧的是这种行为并不是确定的,在一些极其特殊的情况下,会产生意外的结果:
var iframe = document.createElement( ' iframe ' );
document.body.appendChild(iframe);
var xArray = window.frames[window.frames.length - 1 ].Array;
var arr = new xArray( 1 , 2 , 3 ); // [1,2,3]
alert(arr instanceof Array); // false
下面是Johg Resig 《pro javacript Techniques》书中的一张列表:
Duck Typing
在犀牛书里,提到一句老话:”如果走路像鸭子,叫声像鸭子,那他就是鸭子”。换而言之,对于Array来说,如果一个对象有splice和join属性,那它就是一个Array:
function isArray(o) {
return o != null && typeof o === ‘object’ &&
' splice ' in o && ' join ' in o;
}
显然,鸭子检测很容易误把自造的天鹅也当成鸭子:
alert(isArray({ ' splice ' : '' , ' join ' : '' })); // true
注:buck typing并不关注于类型,它关注的是行为,它是实际作用是相互之间约定一种行为接口,好实现类似于多态的调用
Object.toString
ECMA-262中的解释:
Object.prototype.toString()
when the toString method is called,the following steps are taken:
1.get the [[Class]] property of this object //得到内部属性[[Class]]
2.conpute a string value by concatenating the three strings “[object”,Result(1),and”]” //构造一个字符串类型似于[object xxx]
3.return results(2) //返回第2条的执行结果
注:[[Class]]为对象的内部属性,无法真接访问到,这样,就有了:
function isArray(o) {
return Object.prototype.toString.call(o) === ' [object Array] ' ;
}
因为是字符串比较,也就解决了环境问题和语法灵活性所带来的变化,因此比较稳定。好,讲到现在,想必大家对javascript类型判断应该有一个较为深入的理解,我想通过自已的能力,应该也可以写一个比较完善的类型判断函数,那下面就来看一下我是如何实现的。
var is = function (obj,type) {
var toString = Object.prototype.toString;
var _baseTypes = { ' undefined ' : ' undefined ' , ' number ' : ' number ' , ' boolean ' : ' boolean ' , ' string ' : ' string ' };
return (_baseTypes[ typeof obj] === type) ||
(type === " Null " && obj === null ) ||
(type === ' Function ' && " object " === typeof document.getElementById ?
/ ^\s*\bfunction\b / .test( "" + obj):toString.call(obj).slice( 8 , - 1 ) === type) ||
obj instanceof type;
};
因为考虑到实用性,这里是通过传入对象obj和期望类型type,返回boolean值,true为obj为type类型,false为obj不为type类型来实现的。首先,var toString = Object.prototype.toString;这里保存了一份对Object的原生toString方法的引用,方便后面使用:
var _baseTypes = { ' undefined ' : ' undefined ' , ' number ' : ' number ' , ' boolean ' : ' boolean ' , ' string ' : ' string ' };
这里保存了一份对于typeof可以检测出来的基本数据类型的对象列表,其键类型名称,值为typeof该类型的结果。然后:进行类型的检测,返回结果。
(_baseTypes[typeof obj] === type) :检测是否为基本数据类型
(type === ‘Null’ && obj === null):因为null实际上属于Object类型,因此typeof null 和Object.prototype.toString(null)返回的结果都为object和[Object object]
在实际需求中,我们通常希望将null单独列出来作为一种类型来进行判断:
(type === ' function ' && ' object ' === typeof document.getElementById ? / ^\s*\bfunction\b / .test( "" + obj):toString.call(obj).slice( 8 , - 1 ) === type)
这里实际上是在判断obj是否是一个函数,而IE6存在bug,无法正确识别getElementById这类函数,因此做了上些特殊的处理。
obj instanceof type:判断obj是否为type的实例
这里主要是来处理一引起特殊情况,如一些自定义对象的问题。
function Animal() {}
function SubArray() {}
SubArray.prototype = [];
var toString = Object.prototype.toString;
alert(toString( new Animal()));
alert(toString( new SubArray()));
// firefox: [object Window]
// ie: [object Object]
// chrome: [object global]
alert( new SubArray() instanceof Array); // true
alert( new Animal() instanceof Animal); // true
好,并不多了,最后我们来看一个测试结果:
<! DOCTYPE HTML PUBLIC " -//W3C//DTD HTML 4.01 Transitional//EN " >
< html >
< head >
< title > typecheck.html < / title>
< meta http - equiv = " keywords " content = " keyword1,keyword2,keyword3 " >
< meta http - equiv = " description " content = " this is my page " >
< meta http - equiv = " content-type " content = " text/html; charset=UTF-8 " >
<!--< link rel = " stylesheet " type = " text/css " href = " ./styles.css " >-->
< script type = " text/javascript " >
var is = function (obj,type) {
var toString = Object.prototype.toString;
var _baseTypes = { ' undefined ' : ' undefined ' , ' number ' : ' number ' , ' boolean ' : ' boolean ' , ' string ' : ' string ' };
return (_baseTypes[ typeof obj] === type) ||
(type === " Null " && obj === null ) ||
(type === ' Function ' && " object " === typeof document.getElementById ?
/ ^\s*\bfunction\b / .test( "" + obj):toString.call(obj).slice( 8 , - 1 ) === type) ||
obj instanceof type;
};
window.onload = function (){
var msg = document.getElementById( " msg " );
function addMsg(m){
msg.innerHTML += m + " <br /> " ;
}
// 判断基本数据类型
addMsg( " 1,number " + " : " + is( 1 , ' number ' ));
addMsg( " abc,string " + " : " + is( " abc " , " string " ));
addMsg( " true,boolean " + " : " + is( true , " boolean " ));
addMsg( " undefined,undefined " + " : " + is(undefined, ' undefined ' ));
// 判断引用数据类型
addMsg( " null,Null " + " : " + is( null , " Null " ));
addMsg( " new String(''),String " + " : " + is( new String( "" ), " String " ));
addMsg( " {},Object " + " : " + is({}, " Object " ));
addMsg( " [],Array " + " : " + is([], " Array " ));
addMsg( " /foo/,RegExp " + " : " + is( / foo / , " RegExp " ));
try { 0 ()} catch (e) {
addMsg( " try/catch(e),Error " + " : " + is(e, " Error " ));
}
addMsg( " new Date(),Date " + " : " + is( new Date(), " Date " ));
addMsg( " new Number(123),Number " + " : " + is( new Number( 123 ), " Number " ));
addMsg( " new Boolean(true),Boolean " + " : " + is( new Boolean( true ), " Boolean " ));
addMsg( " function(){},Function " + " : " + is( function (){}, " Function " ));
function SubArray() {}
SubArray.prototype = [];
addMsg( " SubArray,Array " + " : " + is( new SubArray(),Array));
}
< / script>
< / head>
< body >
< div id = " msg " >< / div>
< / body>
< / html>
兼容判断类型列表:
基本数据类型 undefined,string,number,boolean
复合数据类型 Date,String,Boolean,Number,Object,Function,Array,RegExp,Error
其他 instanceof 的范畴,参考:
http://lifesinger.org/blog/2009/02/javascript-type-check-1/
http://www.planabc.net/2010/01/23/repair_the_bug_of_isfunction_method_in_jquery/
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容