Javascript类型检测
原地址 http://www.cnblogs.com/fool/archive/2010/10/07/javascrpt.html
开门见山,我们先来看一下代码:
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;
}
但是比较悲剧的是这种行为并不是确定的,在一些极其特殊的情况下,会产生意外的结果:
<div
class
=
"cnblogs_Highlighter"
><pre
class
=
"brush:javascript"
>
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
</pre>
</div>
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/
Javascript类型检测的更多相关文章
- 谈谈JavaScript类型检测
javascript内置的类型检测机制并非完全可靠.比如typeof操作符,并不能准确的判断数据是哪个类型,比如:数组和对象就不能通过typeof来区分. typeof [] ==="o ...
- javascript 类型检测
javascript数据类型分为简单数据类型和复杂数据类型.简单数据类型分为string,number,boolean,defined,null,复杂数据类型为Object.类型检测在写代码可能会非常 ...
- JavaScript类型检测汇总
曾经我以为JavaScript中的类型检测只要使用 typeof 或 instanceof 就可以通通解决.后来我发现我是too young too naive啊!早说过JavaScript是 ...
- JavaScript 类型 检测
前言 ECMAScript中有5种数据类型,分别为Number,Boolean,Null,Undifined和String,以及一种复杂的数据类型Object(由名值对组成,是这门语言所有对象的基础类 ...
- JavaScript类型检测, typeof操作符与constructor属性的异同
*#type.js function Person(name, age) { this.name = name; this.age = age; } var d = {an: 'object'}; v ...
- JavaScript——类型检测
要检测一个变量是否是基本数据类型,可以用 Typeof 操作符.如果我们想知道它是什么类型的对象,我们可以用instanceof 操作符,语法如下所示: result=variable instanc ...
- javascript类型与类型检测
1.javascript类型: 注:包装对象:如"hello".length实际为js为我们隐式创建了一个String临时对象,去调用该对象的length属性,调用过后再将该临时对 ...
- 小结 javascript中的类型检测
先吐槽一下博客园的编辑器,太不好用了,一旦粘贴个表格进来就会卡死,每次都要用html编辑器写,不爽! 关于javascript的类型检测,早在实习的时候就应该总结,一直拖到现在,当时因为这个问题还出了 ...
- JavaScript的三种类型检测typeof , instanceof , toString比较
1.typeof typeof是js的一个操作符,在类型检测中,几乎没有任何用处. typeof 返回一个表达式的数据类型的字符串,返回结果为javascript中的基本数据类型,包括:number. ...
随机推荐
- ER图与UML图
ER图:实体-联系图(Entity-Relation Diagram)用来建立数据模型,在数据库系统概论中属于概念设计阶段,ER图提供了表示实体(即数据对象).属性和联系的方法,用来描述现实世界的概念 ...
- webview与JavaScript之间的交互
据说WebView的强大之处就是能和JavaScript进行交互调用. 参考博客:http://droidyue.com/blog/2014/09/20/interaction-between-jav ...
- Web Service和Servlet的区别(转)
Servlet是Java对于Web开发而产生的一项技术,可以说Servlet技术是Java专有的,它是服务器端的技术,客户端通常是浏览器. WebService是在DCOM/CORBA等分布式技术之后 ...
- php代码20个实用技巧 ------ 转发自菜鸟教程
1.不要实用相对路径 常常会看到: require_once('../../lib/some_class.php'); 该方法有很多缺点:它首先查找指定的php包含路径,然后查找当前目录,因此会检查过 ...
- 在eclipse上安装 Marketplace Client
Eclipse Marketplace是个插件应用商店,很实用的一个功能. 打开 eclipse,help--Eclipse Marketplace Client就能找到 有的eclipse中没有这个 ...
- struts2 + jquery 开发环境下的ajax构建方法(action写法 + struts.xml配置 + js调用代码)
1.action写法 public class RegisterAction extends ActionSupport { private InputStream inputStream; /** ...
- PHP中date函数参数详解
date函数输出当前的时间echo date('Y-m-d H:i:s', time()); // 格式:xxxx-xx-xx xx:xx:xx 第一个参数的格式分别表示: a - "am& ...
- [LeetCode]题解(python):148-Sort List
题目来源: https://leetcode.com/problems/sort-list/ 题意分析: 用nlog(n)的时间复杂度实现一个链表的排序. 题目思路: 用归并排序的思想,将链表用快慢指 ...
- Werkzeug源码阅读笔记(三)
这次主要讲下werkzeug中的Local. 源码在werkzeug/local.py Thread Local 在Python中,状态是保存在对象中.Thread Local是一种特殊的对象,它是对 ...
- C# Socket SSL通讯笔记
一.x.509证书 1.制作证书 先进入到vs2005的命令行状态,即:开始-->程序-->Microsoft Visual Studio 2005-->Visual Studio ...