JavaScript判断对象的类型

  这几天看了些有关JavaScript判断对象类型的介绍,感觉比较好,但是都不太全。于是总结一下,主要有constructor属性、typeof操作符、instanceof操作符和Object.prototype.toString()方法这四个方式来判断对象的类型。


  constructor属性


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

  

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

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

  

 //basic objects
 var obj = {name: "obj"};
 obj.constructor === Object;//true

 //self defined "class"
 var Foo = function(){};
 var f = new Foo();
 f.constructor === Foo;//true

 //primitive types
 //Number
 var num = 1;
 num.constructor === Number;//true
 var nan = NaN;
 nan.constructor === Number;//true
 //Boolean
 var b = true;
 b.constructor === Boolean;//true
 //String
 var s = "string";
 s.constructor === String;//true
 //Function
 var Fun =function(){};
 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]。下面的代码形成了原型链 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"这几种。

  

TypeResult
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的结果的首字母是小写的。

     


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值