javascript中对变量类型的推断

本文正式地址:http://www.xiabingbao.com/javascript/2015/07/04/javascript-type

在JavaScript中,有5种基本数据类型和1种复杂数据类型,基本数据类型有:UndefinedNullBooleanNumberString。复杂数据类型是ObjectObject中还细分了非常多详细的类型,比方:ArrayFunctionDate等等。今天我们就来探讨一下,使用什么方法推断一个出一个变量的类型。

在解说各种方法之前。我们首先定义出几个測试变量,看看后面的方法到底能把变量的类型解析成什么样子,以下几个变量差点儿相同包括了我们在实际编码中经常使用的类型。

var num  = 123;
var str  = 'abcdef';
var bool = true;
var arr  = [1, 2, 3, 4];
var json = {name:'wenzi', age:25};
var func = function(){ console.log('this is function'); }
var und  = undefined;
var nul  = null;
var date = new Date();
var reg  = /^[a-zA-Z]{5,20}$/;
var error= new Error();

1. 使用typeof检測

我们平时用的最多的就是用typeof检測变量类型了。

这次,我们也使用typeof检測变量的类型:

console.log(typeof num, typeof str, typeof bool, typeof arr, typeof json, typeof func, typeof und, typeof nul, typeof date, typeof reg, typeof error
);
// number string boolean object object function undefined object object object object

从输出的结果来看,arr, json, nul, date, reg, error 全部被检測为object类型。其它的变量能够被正确检測出来。当须要变量是否是numberstringbooleanfunctionundefined, json类型时。能够使用typeof进行推断。其它变量是推断不出类型的,包括null。

还有。typeof是区分不出arrayjson类型的。由于使用typeof这个变量时,array和json类型输出的都是object

2. 使用instance检測

在 JavaScript 中,推断一个变量的类型尝尝会用 typeof 运算符。在使用 typeof 运算符时採用引用类型存储值会出现一个问题,不管引用的是什么类型的对象,它都返回 “object”。ECMAScript 引入了还有一个 Java 运算符 instanceof 来解决问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。

与 typeof 方法不同的是,instanceof 方法要求开发人员明白地确认对象为某特定类型。

比如:

function Person(){}
var Tom = new Person();
console.log(Tom instanceof Person); // true

我们再看看以下的样例:

function Person(){}
function Student(){}
Student.prototype = new Person();
var John = new Student();
console.log(John instanceof Student); // true
console.log(John instancdof Person);  // true

instanceof还能检測出多层继承的关系。

好了。我们来使用instanceof检測上面的那些变量:

console.log(num instanceof Number,str instanceof String,bool instanceof Boolean,arr instanceof Array,json instanceof Object,func instanceof Function,und instanceof Object,nul instanceof Object,date instanceof Date,reg instanceof RegExp,error instanceof Error
)
// num : false 
// str : false 
// bool : false 
// arr : true 
// json : true 
// func : true 
// und : false 
// nul : false 
// date : true 
// reg : true 
// error : true

从上面的执行结果我们能够看到,num, str和bool没有检測出他的类型,可是我们使用以下的方式创建num,是能够检測出类型的:

var num = new Number(123);
var str = new String('abcdef');
var boolean = new Boolean(true);

同一时候,我们也要看到,und和nul是检測的Object类型,才输出的true,由于js中没有UndefinedNull的这样的全局类型,他们und和nul都属于Object类型,因此输出了true。

3. 使用constructor检測

在使用instanceof检測变量类型时。我们是检測不到number, ‘string’, bool的类型的。

因此,我们须要换一种方式来解决问题。

constructor本来是原型对象上的属性,指向构造函数。可是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的。

我们先来输出一下num.constructor的内容,即数字类型的变量的构造函数是什么样子的:

function Number() { [native code] }

我们能够看到它指向了Number的构造函数。因此,我们能够使用num.constructor==Number来推断num是不是Number类型的。其它的变量也相似:

function Person(){}
var Tom = new Person();// undefined和null没有constructor属性
console.log(Tom.constructor==Person,num.constructor==Number,str.constructor==String,bool.constructor==Boolean,arr.constructor==Array,json.constructor==Object,func.constructor==Function,date.constructor==Date,reg.constructor==RegExp,error.constructor==Error
);
// 全部结果均为true

从输出的结果我们能够看出,除了undefined和null。其它类型的变量均能使用constructor推断出类型。

不过使用constructor也不是保险的,由于constructor属性是能够被改动的,会导致检測出的结果不对,比如:

function Person(){}
function Student(){}
Student.prototype = new Person();
var John = new Student();
console.log(John.constructor==Student); // false
console.log(John.constructor==Person);  // true

在上面的样例中,Student原型中的constructor被改动为指向到Person,导致检測不出实例对象John真实的构造函数。

同一时候,使用instaceof和construcor,被推断的array必须是在当前页面声明的!比方。一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量。这时推断该变量。Array == object.constructor;会返回false; 
原因: 
1、array属于引用型数据。在传递过程中。不过引用地址的传递。 
2、每一个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所相应的构造函数。是子页面的Array对象。父页面来进行推断,使用的Array并不等于子页面的Array。切记。不然非常难跟踪问题!

4. 使用Object.prototype.toString.call

我们先不管这个是什么,先来看看他是怎么检測变量类型的:

console.log(Object.prototype.toString.call(num),Object.prototype.toString.call(str),Object.prototype.toString.call(bool),Object.prototype.toString.call(arr),Object.prototype.toString.call(json),Object.prototype.toString.call(func),Object.prototype.toString.call(und),Object.prototype.toString.call(nul),Object.prototype.toString.call(date),Object.prototype.toString.call(reg),Object.prototype.toString.call(error)
);
// '[object Number]' '[object String]' '[object Boolean]' '[object Array]' '[object Object]'
// '[object Function]' '[object Undefined]' '[object Null]' '[object Date]' '[object RegExp]' '[object Error]'

从输出的结果来看,Object.prototype.toString.call(变量)输出的是一个字符串,字符串里有一个数组,第一个參数是Object,第二个參数就是这个变量的类型,并且,全部变量的类型都检測出来了,我们只须要取出第二个參数就可以。

或者能够使用Object.prototype.toString.call(arr)=="object Array"来检測变量arr是不是数组。

我们如今再来看看ECMA里是是怎么定义Object.prototype.toString.call的:

Object.prototype.toString( ) When the toString method is called, the following steps are taken: 
1. Get the [[Class]] property of this object. 
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”. 
3. Return Result (2)

上面的规范定义了Object.prototype.toString的行为:首先,取得对象的一个内部属性[[Class]],然后根据这个属性,返回一个相似于”[object Array]”的字符串作为结果(看过ECMA标准的应该都知道,[[]]用来表示语言内部用到的、外部不可直接訪问的属性。称为“内部属性”)。利用这种方法,再配合call,我们能够取得不论什么对象的内部属性[[Class]]。然后把类型检測转化为字符串比較,以达到我们的目的。

5. jquery中$.type的实现

在jquery中提供了一个$.type的接口,来让我们检測变量的类型:

console.log($.type(num),$.type(str),$.type(bool),$.type(arr),$.type(json),$.type(func),$.type(und),$.type(nul),$.type(date),$.type(reg),$.type(error)
);
// number string boolean array object function undefined null date regexp error

看到输出结果,有没有一种熟悉的感觉?对,他就是上面使用Object.prototype.toString.call(变量)输出的结果的第二个參数呀。

我们这里先来对照一下上面全部方法检測出的结果,横排是使用的检測方法, 竖排是各个变量:

类型推断typeofinstanceofconstructortoString.call$.type
numnumberfalsetrue[object Number]number
strstringfalsetrue[object String]string
boolbooleanfalsetrue[object Boolean]boolean
arrobjecttruetrue[object Array]array
jsonobjecttruetrue[object Object]object
funcfunctiontruetrue[object Function]function
undundefinedfalse-[object Undefined]undefined
nulobjectfalse-[object Null]null
dateobjecttruetrue[object Date]date
regobjecttruetrue[object RegExp]regexp
errorobjecttruetrue[object Error]error
长处使用简单,能直接输出结果能检測出复杂的类型基本能检測出全部的类型检測出全部的类型-
缺点检測出的类型太少基本类型检測不出,且不能跨iframe不能跨iframe,且constructor易被改动IE6下undefined,null均为Object-

这样对照一下,就更能看到各个方法之间的差别了,并且Object.prototype.toString.call$type输出的结果真的非常像。我们来看看jquery(2.1.2版本号)内部是怎么实现$.type方法的:

// 实例对象是能直接使用原型链上的方法的
var class2type = {};
var toString = class2type.toString;// 省略部分代码...type: function( obj ) {if ( obj == null ) {return obj + "";}// Support: Android<4.0, iOS<6 (functionish RegExp)return (typeof obj === "object" || typeof obj === "function") ?(class2type[ toString.call(obj) ] || "object") :typeof obj;
},// 省略部分代码... // Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

我们先来看看jQuery.each的这部分:

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {class2type[ "[object " + name + "]" ] = name.toLowerCase();
});//循环之后,`class2type`的值是: 
class2type = {'[object Boolean]' : 'boolean', '[object Number]'  : 'number','[object String]'  : 'string','[object Function]': 'function','[object Array]'   : 'array','[object Date]'    : 'date','[object RegExp]'  : 'regExp','[object Object]'  : 'object','[object Error]'   : 'error'
}

再来看看type方法:

// type的实现
type: function( obj ) {// 若传入的是null或undefined。则直接返回这个对象的字符串// 即若传入的对象obj是undefined。则返回"undefined"if ( obj == null ) {return obj + "";}// Support: Android<4.0, iOS<6 (functionish RegExp)// 低版本号regExp返回function类型;高版本号已修正,返回object类型// 若使用typeof检測出的obj类型是object或function。则返回class2type的值,否则返回typeof检測的类型return (typeof obj === "object" || typeof obj === "function") ?(class2type[ toString.call(obj) ] || "object") :typeof obj;
}

typeof obj === "object" || typeof obj === "function"时,就返回class2type[ toString.call(obj)

到这儿,我们就应该明白为什么Object.prototype.toString.call和$.type那么像了吧,事实上jquery中就是用Object.prototype.toString.call实现的。把’[object Boolean]’类型转成’boolean’类型并返回。若class2type存储的没有这个变量的类型,那就返回”object”。 
除了”object”和”function”类型。其它的类型则使用typeof进行检測。即numberstringboolean类型的变量,使用typeof就可以。

本文正式地址:http://www.xiabingbao.com/javascript/2015/07/04/javascript-type








本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5202979.html,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393781.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

U盘流畅运行linux发行版,做各种linux发行版的启动U盘方法

偶用tuxboot先移植gparted到16GB的U盘。然后裁剪N个iso 做成一个U盘安装或体验N个系统的多功能盘。选单晒出来&#xff1a;default vesamenu.c32timeout 3000prompt 0menu title Android RHEL6.4 Ubuntu13.04 GpartedMENU BACKGROUND Gsplash.pnglabel 001menu label GRUB4DOSk…

采样次数不同平均值不一样_不同的真石漆装饰效果也是不一样的

外墙真石漆真的是一件很好的产品&#xff0c;具有防火性、防水性、安全且环保、粘力强、永不褪色等特点&#xff0c;无疑是人们较好的选择&#xff0c;在很早之前就已经逐渐的取代了瓷砖和其他石材在人们心中的位置。真石漆的品种不止一种&#xff0c;按照装饰效果我们可以分为…

No-3.Linux 终端命令格式

Linux 终端命令格式 01. 终端命令格式 command [-options] [parameter]说明&#xff1a; command&#xff1a;命令名&#xff0c;相应功能的英文单词或单词的缩写[-options]&#xff1a;选项&#xff0c;可用来对命令进行控制&#xff0c;也可以省略parameter&#xff1a;传给命…

电子设计速成_Web设计速成课程:从一个非设计者到另一个

电子设计速成by Ali Spittel通过Ali Spittel Web设计速成课程&#xff1a;从一个非设计者到另一个 (A Web Design Crash Course: from one non-designer to another) I will preface this by saying that I’m not a professional designer. That being said, I like building…

android项目方法数超过65536的解决办法

2019独角兽企业重金招聘Python工程师标准>>> 当项目的总方法数超过65536个&#xff0c;运行在手机上&#xff0c;指不定会报找不到哪个文件的错。 我把项目的PullRefresh框架切换为SmartRefresh框架出现了方法数超过65536。 此文只是做一下笔记&#xff0c;不多做解…

leetcode1046. 最后一块石头的重量(堆)

有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出两块 最重的 石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#xff1a; 如果 x y&#xff0c;那么两块石头都会被完全…

[Linux]几个armhf的ubuntu源

摘自百度贴吧&#xff0c;留存 http://mirrors.ustc.edu.cn/ubuntu-ports/http://ftp.ubuntu-tw.org/mirror/ubuntu-ports/http://mirror.csclub.uwaterloo.ca/ubuntu-ports/http://mirrors.mit.edu/ubuntu-ports/ 速度从上到下越来越慢 中科技大 > 台湾新北 > 滑铁卢大学…

asp.net Linux 界面,在 ASP.NET 中实现不同角色的用户使用不同登录界面的方法

很多用户在开发 ASP.NET应用程序时都有这样的需求&#xff1a;管理员角色的账户使用管理员的登录界面进行登录&#xff0c;普通用户角色的账户使用普通用户的登录界面进行登录。由于ASP.NET的web.config里只能使用一个 authentication mode"Forms"节点&#xff0c;所…

pandas之Series

知识点 Pandas的数据类型有两种&#xff1a;1、Series 一维&#xff0c;带标签数组2、DataFrame 二维&#xff0c;Series容器Serial对象本质上由两个数组构成&#xff0c;一个数组构成对象的健(index,索引),一个数组构成对象的值(values).因此Series可以看作是键值对(健-->值…

python快乐数字怎么表达_Python经典面试题:这些面试题你会了吗?

前言什么&#xff1f;你要去找工作&#xff1f;先别急着找工作&#xff0c;先把下面的python面试题先给看了吧&#xff0c;不然你就只是去面试而不是找工作。话说不打没准备的仗&#xff0c;下面这些基本的面试题都不会你怎么可能找到工作呢&#xff1f;还是先把下面的东西1、P…

【swift学习笔记】三.使用xib自定义UITableViewCell

使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell&#xff0c;拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewcell上 并给我们的xib一个标识 为了学习&#xff0c;我这里的xib和后台的class是分开建的。我们再建一个cocoa touc…

leetcode455. 分发饼干(贪心算法)

假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。对每个孩子 i &#xff0c;都有一个胃口值 gi &#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j &#xff0c;都有一个尺寸 sj 。…

slack 使用说明_我如何使用Node和Botkit构建HR Slack Bot

slack 使用说明为什么要创建Slack Bot&#xff1f; (Why create a Slack Bot ?) I am an HR professional. More specifically I am a Human Resources Information System (HRIS) Consultant. I work with Application Tracking Systems, Learning Management Systems, and C…

linux 监听数据包,linux下网络监听与发送数据包的方法(即libpcap、libnet两种类库的使用方法)...

linux下可以用libpcap函数库实现监听数据包&#xff0c;使用libnet 函数库发送数据包安装:在命令行下apt-get install 就可以了libpcap的使用:/*author hjjdate 2011-1-21function:capture packet with the ruler and output the packet informationmodify 2011-1-23function:g…

命令模式(Command Pattern)

1命令模式是一个高内聚的模式。定义如下&#xff1a;将一个请求封装成一个对象&#xff0c;从而让你使用不同的请求把客户端参数化&#xff0c;对请求排队或者记录请求日志&#xff0c;可以提供命令的撤销和恢复功能。 2.角色说明&#xff1a; ● Receive接收者角色 该角色就…

BZOJ 3270: 博物馆

传送门 显然可以状态转移&#xff1a; 设 $f[k][x][y]$ 表示第 $k$ 时刻&#xff0c;第一个人在 $x$ &#xff0c;第二个人在 $y$ 时的概率 那么转移显然&#xff1a; $f[k][x][y]\sum_{u}\sum_{v}f[k-1][u][v]*(1-P_u)(1-P_v)/du[u]/du[v]$ 其中 $u$ 和 $x$ 有边相连&#xff…

graphpad7.04多组比较p值_同是折线图为何你却这么优秀,这才是多组数据作图应该有的样子...

相信大家对Excel做折线图应该不陌生&#xff0c;在展示数据的时候&#xff0c;图表是一种最好的展示方法。但是经常会碰到一种尴尬的事情就是&#xff0c;当数据维多比较多的时候&#xff0c;做出的图表就会显得非常难看。今天我们就来学习一下&#xff0c;多组数据怎么做折线图…

Logic-算法-八个箱子找一个最轻的

ylbtech-Arithmetic:Logic-算法-八个箱子找一个最轻的-- -- ylb&#xff1a;算法-- Type:算法[logic]-- munu:八个箱子-找一个最轻的-- thankyou:gaoZhimin -- 7:11 2012/3/17-- 有八个正方形的箱子&#xff0c;外观大小都一样&#xff0c;其中七个是50斤的&#xff0c;一个是…

由衷的信来激励有抱负的开发人员

by Logan Wright洛根赖特(Logan Wright) 由衷的信来激励有抱负的开发人员 (A heartfelt letter to inspire the aspiring developer) I’m writing a letter to my friend. You should read it. He studies Computer Science, and he hates it. I build React Apps and I love…

linux 运行 chom,Hadoop安装-单节点/伪分布(2.7.3)

1&#xff0c;下载Hadoop目前在Ubuntu的软件库里面 没有发现Hadoop的压缩包&#xff0c;没猜错Hadoop不是可执行文件 只是一个压缩包吧&#xff01;所以我们只能自己到官网下载(http://hadoop.apache.org/releases.html)&#xff1b;在Apache社区中&#xff0c;下载软件的时候…