jQuery的makeArray有其局限性(1.3.4还有bug),我自己实现了一个,不过涉及N多辅助方法。
var dom = {}, _toString = Object.prototype.toString, _slice = Array.prototype.slice; dom.is = function(obj,type) { return _toString.call(obj).match(/^\[object\s(.*)\]$/)[1] === type; } dom.isArray = function (obj) { return dom.is(obj,"Array"); } dom.isNumber = function (obj) { return dom.is(obj,"Number"); } dom.isString = function (obj) { return dom.is(obj,"String"); } dom.isArrayLike = function (obj) {//包括Array if(dom.isArray(obj) || obj.callee) return true; if(dom.is(obj,'NodeList')) return true; if(dom.is(obj,'HTMLCollection')) return true; //不能为字符串,不能为window,具有length属性 if(dom.isNumber(obj.length) && !dom.isString(obj) && !obj.eval){ if(obj.nextNode || obj.item) return true; var n = obj.length - 1 < 0 ? 0 : obj.length - 1 ; //如果是具有数字键或length属性的对象,如jQuery对象 if(obj.hasOwnProperty(n) && obj.hasOwnProperty(0)) return true return false; } return false; } dom.toArray = function (arr) { //把普通对象变成原生数组对象 if(arguments.length === 0 || arr === null){ return []; }else if(arr.callee){//如果是Arguments对象 return _slice.call(arr); }else if(dom.isArray(arr)){//如果Array对象返回一个克隆 return arr.concat(); }else if(dom.isArrayLike(arr)){ try{//jQuery对象,dom对象,el.getElementsByTagName得到的HTMLCollection //与el.childNodes得到的NodeList return _slice.call(arr); }catch(e){//IE用slice处理元素或节点集合会出错,只能慢慢拷贝 var ret = [], i = arr.length; while (i) ret[--i] = arr[i]; //Clone数组 return ret; } }else {//普通函数,单个元素节点,字符串,数字,window对象 return [arr]; } }
早期尝试使用Ext.isIterable,不过它有点小BUG,如放一个函数进去,它会返回undefined,好歹返回false嘛,另对于用户自定义的类数组对象无法检测,残念!不过我的isArrayLike也不完美,自定义的东西随意性太大了,暂时没办法一网打尽……以后慢慢改进!
下面是测试:
//2010.2.27更新 var is = function(obj,type){ return String(Object.prototype.toString.call(obj)).slice(8,-1) === type; } var toArray = function (obj) { var result = []; if ( obj != null ) { //对于普通对象,window对象,字符串,函数,select元素节点 //window.length为frames.length,function.length为其形参的长度,select.length为其options.length if ( obj.length == null || is(obj,"String") || is(obj,"Function") || obj.eval || obj.nodeType ) { result = [obj] } else { try{//IE下,slice在转换HTMLCollection,NodeList,IXMLDOMNodeList 会失败 result = slice.call(obj); } catch(e){ var i = obj.length while( i ) result[--i] = obj[i]; } } } return result; }