先看prototype源代码,有这么一个函数
isArray: function(object) { return object != null && typeof object == "object" && 'splice' in object && 'join' in object; },
为什么判断一个对象是否为Array的方法里要同时验证splice和join?因为splice和join是Array对象独有的方法。
同样的一幕,也发生在jquery中,
makeArray : function(array) { var ret = [], i; if (array != null) { i = array.length; // The window, strings (and functions) also have 'length' if (i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval) { ret[0] = array; } else { while (i) { ret[--i] = array[i]; } } } return ret; },
这个函数先求出array.length,请注意array是个参数,不是数组!我们不妨把它理解成一个未知的对象。注释提到了 拥有length属性的对象除了Array,还有window、String和Function。(具体表示意义,可以查看《网页制作完全手册》和《JScript 语言参考》),里面的if语句刚好考虑了上面的三种情况:
- typeof array === "string" : 判读参数array是String对象;
- jQuery.isFunction(array) : 判读参数array是Function对象;
- array.setInterval : 判读参数array是window对象;
其中,“拥有setInterval的对象一定是window对象”可以作为一个思路,这也是刚开始提到的prototype判断未知对象是否为Array的方法。道理应该相同,我不知道我理解的对不对?
---------------
2009-7-8
---------------
关于判读某个对象是否为数组的另一种方法:
if (Object.prototype.toString.apply(value) === '[object Array]') { //do sthing }
以上代码摘自 http://www.json.org/json.js 大概第330行。
---------------
2009-8-1
---------------
《JavaScript语言精粹》谈到了如何精确地判断数组:
var is_array = function(value) { return value && typeof value === 'object' && typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length')); };
有关propertyIsEnumerable方法,可以查看js手册。