isXXX方式的类型判断

如果需要判断一个对象是否为Array类型,一般会怎么做呢?

function isArray(obj){
	return obj instanceof Array;
}

或者类似的

function isArray(obj){
	return obj.constructor === Array;
}

补充一点基础知识,高手无视~

A instanceof B 检测原理:
对象A的原型链是否存在对象B的prototype,如果在,返回true;如果不在,则返回false。不过有一个特殊情况,当对象B的prototype为null将会报错。
function A(){	
}
function B(){

}
A.prototype = new B();	//A.prototype.__proto__ === B.prototype,所以符合instanceof检测
var a = new A();
a instanceof B;  		//输出true
简单点说,如果B是对象A的类或父类(父类的父类...),返回true,否则返回false。
constructor 指向原理:
function A(){}
A.prototype.constructor
这里会指向A,其实就是指向构造函数,但我们可以改写,如A.prototype.constructor = {}

这两种方法看似解决了需求,但是前端的难度就在于各种层出不穷的问题,这次也一样,如果一个数组来自另一个frame,那它的constructor将是另一个对象。

var iframe = document.createElement('iframe');   
document.body.appendChild(iframe);   
iArray = window.frames[window.frames.length-1].Array;   
var arr = new iArray(1,2,3);  
console.log(arr instanceof Array);
console.log(arr.constructor === Array); 
console.log(arr.constructor)

  

 结果如下:

Chrome:false  false  function Array() { [native code] }

FireFox6:true  true  [undefined]

   Opera:false  false  function Array() { [native code] }

  Safari:true  true  function Array() { [native code] }

     IE9:false  false  function Array() { [native code] }

好吧,我承认我很蛋疼地去测试了这些数据,总之结论就是上面两种判断方式不好使。

感谢伟大的网友,已经有人找到ECMA-262的依据了

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()时,js引擎会这么做:

  1. 获得对象的一个内部属性[[Class]],暂取名为c;([[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)

  2. 连接三个字符串"[object",c,"]"

  3. 返回结果

利用这个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。

最终版

function isArray(obj){
	return Object.prototype.toString.call(obj) === '[object Array]';
}

已有类库在使用此方法,所以我们可以放心使用了!

其他的对象,如RegExp,也可类似的进行判断。

 

posted @ 2011-08-21 00:50  越己  阅读(1881)  评论(6编辑  收藏  举报