最近阅读了一些关于JavaScript判断对象类型的文章。总结下来,主要有constructor属性、typeof操作符、instanceof操作符和Object.prototype.toString()方法这四个方式来判断对象的类型。

constructor属性

构造函数预定义的constructor属性是构造函数本身。

var Foo = function(){};
Foo.prototype.constructor === Foo;//true

通过new调用构造函数所生成的对象以构造函数的prototype属性为原型。虽然JavaScript中没有类的概念,但是构造函数的作用同类的名称相似,是对象类型的标识。访问对象继承的constructor属性可以查看对象的类型。原始类型的变量也可以访问constructor属性,因为在访问的时候JavaScript形成了一个包装对象。

 1 //basic objects
2 var obj = {name: "obj"};
3 obj.constructor === Object;//true
4
5 //self defined "class"
6 var Foo = function(){};
7 var f = new Foo();
8 f.constructor === Foo;//true
9
10 //primitive types
11 //Number
12 var num = 1;
13 num.constructor === Number;//true
14 var nan = NaN;
15 nan.constructor === Number;//true
16 //Boolean
17 var b = true;
18 b.constructor === Boolean;//true
19 //String
20 var s = "string";
21 s.constructor === String;//true
22 //Function
23 var Fun =function(){};
24 Fun.constructor === Function;//true;

然而,constructor属性是可以重新复制或者覆盖的,这会引起类型判断的错误。即使我们一般不会刻意去给constructor属性赋值,但是有一些情况下constructor属性的值和我们所期望的值不同。看下面例子:

var baseClass = function(){};
var derivedClass = function(){};
derivedClass.prototype = new baseClass(); var obj = new derivedClass();
obj.constructor === derivedClass;//false;
obj.constructor === baseClass;//true;

因为子类的prototype以父类的实例为原型,所以通过子类实例访问constructor就是父类构造函数。因此在JavaScript面向对象编程中,我们会在定义子类时加上一句代码来纠正constructor属性。

derivedClass.prototype.constructor = derivedClass;

使用constructor进行判断变量类型虽然方便,但是不见得特别安全,所以需要小心。

cross-frame和cross-window问题:

如果判断来自不同frame或来自不同window的变量的对象的类型,那么constructor属性无法正常工作。因为不同window的核心类型不同[1]。

使用instanceof操作符

instanceof操作符判断一个对象的原型链中是否存在某个构造函数的prototype属性[2]。原型链的概念可以阅读JavaScript面向对象编程(一)原型与继承。下面的代码形成了原型链obj1->derivedClass.prototype->baseClass.prototype->...->Object.prototype。Object.prototype是所有对象的原型,anyObj instanceof Object === true。

var baseClass = function(){};
var derivedClass = function(){};
derivedClass.prototype = new baseClass();//use inheritance var obj1 = new derivedClass();
obj1 instanceof baseClass;//true
obj1 instanceof derivedClass;//true
obj1 instanceof Object;//true obj2 = Object.create(derivedClass.prototype);
obj2 instanceof baseClass;//true
obj2 instanceof derivedClass;//true
obj2 instanceof Object;//true

constructor属性可以应用到除了null和undefined之外的原始类型(数字、字符串、布尔类型)。而instanceof不可,但是可以使用包装对象的方法进行判断。

3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false new Number(3) instanceof Number // true
new String('abc') instanceof String //true
new Boolean(true) instanceof Boolean //true

然而,instanceof在cross-frame和cross-window的情况下也无法正常工作。

使用 Object.prototype.toString()方法

Object.prototype.toString()方法是一个底层的方法,使用它可以返回一个字符串,该字符串表明了对象的类型。也可以用于判断null和undefined。下面列出了多数常见的类型。

Object.prototype.toString.call(3);//"[object Number]"
Object.prototype.toString.call(NaN);//"[object Number]"
Object.prototype.toString.call([1,2,3]);//"[object Array]"
Object.prototype.toString.call(true);//"[object Boolean]"
Object.prototype.toString.call("abc");//"[object String]"
Object.prototype.toString.call(/[a-z]/);//"[object RegExp]"
Object.prototype.toString.call(function(){});//"[object Function]" //null and undefined in Chrome and Firefox. In IE "[object Object]"
Object.prototype.toString.call(null);//"[object Null]"
Object.prototype.toString.call(undefined);//"[object Undefined]" //self defined Objects
var a = new Foo();
Object.prototype.toString.call(a);//"[object Object]" //Typed Wrappers
var b = new Boolean(true);
Object.prototype.toString.call(b);//"[object Boolean]"
var n = new Number(1);
Object.prototype.toString.call(n);//"[object Number]"
var s = new String("abc");
Object.prototype.toString.call(s);//"[object String]"

经常会使用slice方法截取结果中类型的信息:

Object.prototype.toString.call("abc").slice(8,-1);//"String"

使用typeof 运算符

在MDN的一篇文档中已经很详细介绍了这个[3]。typeof能返回的信息较少,有"undefined"、"object"、"boolean"、"number"、"string"、"function"、"xml"这几种。

Type Result
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Host object (provided by the JS environment) Implementation-dependent
Function object (implements [[Call]] in ECMA-262 terms) "function"
E4X XML object "xml"
E4X XMLList object "xml"
Any other object "object"
// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // Despite being "Not-A-Number"
typeof Number(1) === 'number'; // but never use this form! // Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof always return a string
typeof String("abc") === 'string'; // but never use this form! // Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // but never use this form! // Undefined
typeof undefined === 'undefined';
typeof blabla === 'undefined'; // an undefined variable // Objects
typeof {a:1} === 'object';
typeof [1, 2, 4] === 'object'; // use Array.isArray or Object.prototype.toString.call to differentiate regular objects from arrays
typeof new Date() === 'object'; typeof new Boolean(true) === 'object'; // this is confusing. Don't use!
typeof new Number(1) === 'object'; // this is confusing. Don't use!
typeof new String("abc") === 'object'; // this is confusing. Don't use! // Functions
typeof function(){} === 'function';
typeof Math.sin === 'function'; typeof undefined;//"undefined"
typeof null;//"object" This stands since the beginning of JavaScript
typeof /s/ === 'object'; // Conform to ECMAScript 5.1

typeof 包装对象的结果是‘object’需要注意。这里不评价好与不好(如果需要区分包装对象和原始类型呢)。但是typeof不是一个健壮的方法,要小心使用。比如:

var s = "I am a string";
typeof s === "string";
//Add a method to String
String.prototype.A_String_Method = function(){
console.log(this.valueOf());
console.log(typeof this);
};
s.A_String_Method();
//I am a string
//object

这里为了表述,在String构造函数的prototype中添加了一个方法。可以看出,字符串处理函数都是将字符串变成一个包装对象,所以typeof的结果是object。要注意,typeof的结果的首字母是小写的。

参考文献:

[1]stackoverflow的一个问答http://stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript

[2]MDN关于instanceof的文章:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

[3]MDN关于typeof的文章:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof

 
 
 

JavaScript判断对象的类型的更多相关文章

  1. JavaScript判断对象类型及节点类型、节点名称和节点值

    一.JavaScript判断对象类型 1.可以使用typeof函数判断对象类型 function checkObject1(){ var str="str"; console.lo ...

  2. Javascript 判断对象是否相等

    在Javascript中相等运算包括"==","==="全等,两者不同之处,不必多数,本篇文章我们将来讲述如何判断两个对象是否相等? 你可能会认为,如果两个对象 ...

  3. Java基础 ----- 判断对象的类型

    1. 判断对象的类型:instanceOf 和 isInstance 或者直接将对象强转给任意一个类型,如果转换成功,则可以确定,如果不成功,在异常提示中可以确定类型 public static vo ...

  4. javascript 判断对象类型

    typeof typeof是一个一元运算符,它返回的结果 始终是一个字符串,对不同的操作数,它返回不同的结果. 此表总结了typeof所有可能的返回值: 操作数类型 返回值 undefined &qu ...

  5. js中判断对象具体类型

    大家可能知道js中判断对象类型可以用typeof来判断.看下面的情况 <script> alert(typeof 1);//number alert(typeof "2" ...

  6. javascript 判断对象的内置类型

    判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法.在toString方法被调用时,会执行下面的操作步骤:1. 获取this对象的[[Class ...

  7. [转] javascript 判断对象是否存在的10种方法总结

    [From] http://www.jb51.net/article/44726.htm Javascript语言的设计不够严谨,很多地方一不小心就会出错.举例来说,请考虑以下情况.现在,我们要判断一 ...

  8. flex 判断对象的类型

    在判断flex对象的类型之前,首先是获取对象类型,获取的方式有: mx.utils.NameUtil.getUnqualifiedClassName(object:Object):String  // ...

  9. JavaScript 判断对象中是否有某属性

    判断对象中是否有某属性的常见方式总结,不同的场景要使用不同的方式. 一.点( . )或者方括号( [ ] ) 通过点或者方括号可以获取对象的属性值,如果对象上不存在该属性,则会返回undefined. ...

随机推荐

  1. 几款web版整合(QQ、msn、icq、yahoo通、Gtalk等)即时聊天http://hi.baidu.com/ejie/blog/item/e89794ef9a9431efce1b3ebd.html

        直到近期为止,我们经常使用的即时聊天工具(QQ.msn等)了Web版,大家不用下载庞大软件,直接打开网页就能够与自己的好友聊天,很方便.在此将时汇总,便于大家查找,节约大家一点时间. 此都是官 ...

  2. 选择29部分有用jQuery应用程序插件(免费点数下载)

    免积分下载:http://download.csdn.net/detail/yangwei19680827/7238711 原文地址:http://www.cnblogs.com/sxwgf/p/36 ...

  3. Struts2.0+Spring3+Hibernate3(SSH~Demo)

    Struts2.0+Spring3+Hibernate3(SSH~Demo) 前言:整理一些集成框架,发现网上都是一些半成品,都是共享一部分出来(确实让人很纠结),这是整理了一份SSH的测试案例,完全 ...

  4. 【Unity 3D】学习笔记四十一:关节

    关节 关节组件能够加入至多个游戏对象中,而加入关节的游戏对象将通过关节连接在一起而且感觉连带的物理效果.须要注意的是:关节必须依赖于刚体组件. 关节介绍 关节一共分为5大类:链条关节,固定关节,弹簧关 ...

  5. getch()、getche()和getchar()函数

    原文:getch().getche()和getchar()函数 getch().getche()和getchar()函数(1) getch()和getche()函数 这两个函数都是从键盘上读入一个字符 ...

  6. 多线程学习之BlockingQueue

    前言: 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列 类,为我们快速搭建高质量的多线程程序带来极大的 ...

  7. ResultSet取结果集多少条记录方法及分页概要

    allst=toconn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); allsql = ...

  8. SQL Server 2008 R2中,变表的右键弹出菜单中的“选择前1000行”为“选择所有行”

    原文:SQL Server 2008 R2中,变表的右键弹出菜单中的"选择前1000行"为"选择所有行" 从SQL Server 2008开始,微软为了提高查询 ...

  9. 增加VMWare开机画面时间,来防止快速跳过而无法进入BIOS

    用记事本打开xx.vmx,在里面添加一行: bios.bootDelay = "30000" 意思是开机后,在开机画面里停留30秒.

  10. 解决Postman发送post数据但是Node.js中req.body接收不到数据的问题[已解决]

    之前编写后台接口,测试数据都是使用的Postman,相当的方便,之前也一直使用get方法,编写Node.js一直没有问题,但是由于要编写一个注册/登陆的功能,所以发送的post数据,后台的逻辑已经编写 ...