`
lllt
  • 浏览: 66690 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Javascript类型检测

 
阅读更多

[尊重原创,转载地址:http://www.cnblogs.com/fool/archive/2010/10/07/javascrpt.html]

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

1 var is = function (obj,type) { 
2     var toString = Object.prototype.toString; 
3     var _baseTypes = {'undefined':'undefined','number':'number','boolean':'boolean','string':'string'};
4     return (_baseTypes[typeof obj]===type)||
5              (type === "Null" && obj === null) ||
6              (type==='Function'&&"object" === typeof document.getElementById ?
7              /^\s*\bfunction\b/.test("" + obj):toString.call(obj).slice(8,-1) === type)||
8              obj instanceof type; 
9 };

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

typeof

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

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

 

instanceof

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

  new String('abc') instanceof String //true

instanceof还可以检测父类型。 

1 function Animal() {};
2 function Pig() {};
3 Pig.prototype = new Animal();
4 alert(new Pig() instanceof Animal); // true

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

Constructor

所有对象都拥有一个constructor属性,它指向该对象的构造函数。

对于复合数据类型,我们可以采用如下方式进行检测:

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

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

1  <div class="cnblogs_Highlighter"><pre class="brush:javascript">var iframe = document.createElement('iframe');
2 document.body.appendChild(iframe);
3 var xArray = window.frames[window.frames.length-1].Array;
4 var arr = new xArray(1, 2, 3); // [1,2,3]
5 alert(arr instanceof Array); //false
6
7 </pre>
8 </div>

 



 下面是Johg Resig 《pro javacript Techniques》书中的一张列表:

Duck Typing 

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

1 function isArray(o) {
2     return o != null && typeof o === ‘object’ &&
3            'splice' in o && 'join' in o;
4 }

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

1 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]]为对象的内部属性,无法真接访问到

这样,就有了:

1 function isArray(o) {
2     return Object.prototype.toString.call(o) === '[object Array]';
3 }

因为是字符串比较,也就解决了环境问题和语法灵活性所带来的变化,因此比较稳定。

 

好,讲到现在,想必大家对javascript类型判断应该有一个较为深入的理解,我想通过自已的能力,应该也可以写一个比较完善的类型判断函数,那下面就来看一下我是如何实现的。

1 var is = function (obj,type) { 
2     var toString = Object.prototype.toString; 
3     var _baseTypes = {'undefined':'undefined','number':'number','boolean':'boolean','string':'string'};
4     return (_baseTypes[typeof obj]===type)||
5              (type === "Null" && obj === null) ||
6              (type==='Function'&&"object" === typeof document.getElementById ?
7              /^\s*\bfunction\b/.test("" + obj):toString.call(obj).slice(8,-1) === type)||
8              obj instanceof type; 
9 };

因为考虑到实用性,这里是通过传入对象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的实例

   这里主要是来处理一引起特殊情况,如一些自定义对象的问题。

 

01 function Animal() {}
02 function SubArray() {}
03 SubArray.prototype = [];
04
05 var toString = Object.prototype.toString;
06 alert(toString(new Animal()));
07 alert(toString(new SubArray()));
08 // firefox: [object Window]
09 // ie: [object Object]
10 // chrome: [object global]
11
12 alert(new SubArray() instanceof Array); // true
13 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 的范畴

参考:



1 http://lifesinger.org/blog/2009/02/javascript-type-check-1/
2 http://www.planabc.net/2010/01/23/repair_the_bug_of_isfunction_method_in_jquery/

 

 

分享到:
评论

相关推荐

    【JavaScript源代码】JavaScript类型检测的方法实例教程.docx

    在JavaScript编程中,类型检测是确保程序正确运行的关键部分。JavaScript是一种动态类型的弱类型语言,这意味着变量可以在不同的时刻存储不同类型的数据。了解如何检测变量的类型对于编写健壮的代码至关重要。下面...

    JavaScript类型检测之typeof 和 instanceof 的缺陷与优化

    在javascript中,typeof 和 instanceof 是用来判断数据类型比较通用的两个方法,这篇文章的目的是通过对这两个方法介绍来分析其存在的不足并提出优化方案。 typeof ——————————————————————...

    如何检测JavaScript的各种类型

    JavaScript类型检测是编程中一项十分重要的技能,因为正确的类型检测能够帮助开发者避免许多潜在的异常和错误。在JavaScript中,类型大致可以分为原始类型和对象类型,其中原始类型包括字符串(string)、数字...

    在SonarQube上使用java自定义JavaScript检测规则

    使用 Java 开发 SonarQube JavaScript 检测规则 在 SonarQube 中使用 Java 开发检测规则是非常重要的,特别是在 JavaScript 项目中检测代码质量。SonarQube 提供了一个强大的平台,允许开发者使用 Java 语言开发...

    Javascript静态类型检测器Flow中文参考指南

    Flow是Facebook推出的一款静态类型检查工具,专为JavaScript设计,用于在代码运行前检测可能存在的类型错误。Flow的目标是提供一种方式,让开发者可以在保持JavaScript动态特性的前提下,引入静态类型检查,提升代码...

    javascript源码检测工具

    JavaScript源码检测工具,如JSLint,是用于提升代码质量、发现潜在错误和编码风格问题的重要辅助工具。JSLint是由Douglas Crockford开发的一款著名JavaScript代码质量检查器,它通过严格的一系列规则来分析代码,...

    javascript中的数据类型检测方法详解.docx

    在JavaScript中,了解数据类型检测方法对于编写高效和健壮的代码至关重要。JavaScript是一种动态类型语言,这意味着变量的类型可以在运行时改变。因此,正确识别变量的数据类型是调试和优化代码的关键。 首先,我们...

    JavaScript引擎JIT代码的类型混淆缺陷检测器.pdf

    JavaScript引擎JIT代码的类型混淆缺陷检测器 JavaScript引擎JIT代码的类型混淆缺陷检测器是一种用于检测JavaScript引擎JIT代码中的类型混淆缺陷的检测器。该检测器基于对JavaScript引擎JIT编译器设计机制的剖析,...

    js检测浏览器类型

    在JavaScript中,检测浏览器类型是常见的需求,这有助于开发者针对不同浏览器实现特定的功能或优化。以下将详细讲解如何使用JavaScript来识别用户所使用的浏览器类型。 首先,JavaScript提供了`navigator`对象,它...

    在javaScript中检测数据类型的几种方式小结

    最后,Object.prototype.toString.call()是一个更详细的数据类型检测方法,它调用了Object原型上的toString方法,能够准确识别出所有JavaScript中的类型。使用此方法时,无论传入什么类型的参数,都会返回一个格式为...

    基于增强代码属性图的JavaScript漏洞检测方法.pdf

    “基于增强代码属性图的JavaScript漏洞检测方法” 本文提出了一种基于增强代码属性图的JavaScript漏洞检测方法,该方法可以有效地检测网络应用中的JavaScript安全漏洞。该方法首先将JavaScript代码的动态特征与静态...

    前端开源库-es-is

    "es-is"是一个专为前端开发者设计的开源库,它是JavaScript类型检测库的一个ES模块友好分支,旨在提供对JavaScript变量类型的精确检查。这个库的出现,使得在现代前端项目中,开发者能够更加灵活、高效地进行类型...

    JavaScript学习笔记之检测客户端类型是(引擎、浏览器、平台、操作系统、移动设备)

    JavaScript中检测客户端类型的详细知识点包括了对访问网页的用户代理字符串UA的分析,以此来确定访问者的浏览器、平台、操作系统、移动设备以及游戏系统等信息。下面详细讲述这些知识点: 1. 用户代理字符串UA:UA...

    面向安卓应用的JavaScript漏洞检测工具.pdf

    由于Android应用程序常常使用WebView组件来嵌入网页内容,JavaScript代码得以与应用程序交互,然而这同时也使得应用程序容易受到特定类型的漏洞攻击。针对这一问题,黄青青、宋巍和钱祥星开发了一款名为JSDroid的...

    碰撞检测 JavaScript

    变量声明(var、let、const)、数据类型(如字符串、数字、布尔值、对象等)、流程控制(条件语句、循环)、函数定义和调用,以及事件处理都是JavaScript编程的基础。 在JavaScript中,碰撞检测通常涉及到坐标系统...

    javascript基本数据类型及类型检测常用方法小结

    在JavaScript中,理解基本数据类型和类型检测是编程的基础。JavaScript提供了六种基本数据类型:Object、Number、String、null、undefined和Boolean。这些类型构成了JavaScript语言的核心,所有的操作都基于这些类型...

    JS类型检测库弥补typeof的问题

    在JavaScript这个动态类型的编程语言中,类型检测是一个常见的需求,因为它的灵活性可能导致一些难以预见的错误。`typeof`操作符是JavaScript内置的用于检测变量类型的工具,但它在处理某些特定情况时存在局限性。...

Global site tag (gtag.js) - Google Analytics