Object.prototype.toString

有这么一个问题,如何判断一个对象是不是一个Array(或者Funciton)

1、instanceof

常规的做法是用instanceof

var a = [];
a instanceof Array

这个在一般情况下能够work,但是在多iframe的环境下就会出现问题,Perfection kills上一篇文章描述了这个问题

The problems arise when it comes to scripting in multi-frame DOM environments. In a nutshell, Array objects created within one iframe do not share [[Prototype]]’s with arrays created within another iframe. Their constructors are different objects and so both instanceof and constructor checks fail:

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]  
// Boom!
arr instanceof Array; // false  
// Boom!
arr.constructor === Array; // false

This “problem” was mentioned by Crockford as far as back in 2003. Doug suggested to try duck-typing and check for a type of one of the Array.prototype methods – e.g.:

typeof myArray.sort == 'function'

2、 Object.prototype.toString

鉴于instanceof 不总是能正常work, 比较通用的方案是利用:Object.prototype.toString

var a = [];
object.prototype.toString.call(a); // [object Array]

工作原理

ecmascript262.3中对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).

简而言之:该函数会获取对象的内部属性[[Class]],这个属性是一个字符串值,表征对象的种类。

规范中[[Class]]的取值有以下几种:

  • "Object"
  • "Array"
  • "Function"
  • "Date"
  • "RegExp"
  • "String"
  • "Number"
  • "Boolean"
  • "Error" for error objects such as instances of ReferenceError, TypeError, SyntaxError, Error, etc
  • "Math" for the global Math object
  • "JSON" for the global JSON object defined on the ECMAScript 5th Ed. spec.
  • "Arguments" for the arguments object (also introduced on the ES5 spec.)
  • "null" (introduced just a couple of days ago in the ES5 errata)
  • "undefined"

Reference

comments powered by Disqus