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,也可类似的进行判断。