Ruby's Louvre

每天学习一点点算法

导航

将"类数组对象"转换成数组对象

javascript与dom有许多瑕疵,如著名的类数组对象Arguments,其他诸如HTMLCollection,NodeList如果它们都是数组的子类,那多省时啊。在标准浏览器中,好像只要对象存在length属性,就能把它转换为数组,但IE就不尽然。

         //※※※※※※※※※※※测试1※※※※※※※※※※※※※※
        function test(){
          alert(arguments)
          arguments = Array.prototype.slice.call(arguments);
          alert(arguments instanceof Array);
          alert(arguments)
        }
        test(1,2,3,4);
        //※※※※※※※※※※※测试2※※※※※※※※※※※※※※
        var htmlcollection = document.getElementsByTagName("h3");
        alert(htmlcollection)
        try{
          htmlcollection = Array.prototype.slice.call(htmlcollection);
          alert(htmlcollection instanceof Array);
          alert(htmlcollection);
        }catch(e){
          alert(e)
        }
        //※※※※※※※※※※※测试3※※※※※※※※※※※※※※
        var sheets = document.styleSheets;
        alert(sheets)
        try{
          sheets = Array.prototype.slice.call(sheets);
          alert(sheets instanceof Array);
          alert(sheets);
        }catch(e){
          alert(e)
        }
        //※※※※※※※※※※※测试4※※※※※※※※※※※※※※
        var arrayLike = {
          0 : '司徒正美',
          1 : '司徒正美',
          2 : '司徒正美',
          length : 3
        };
        alert(arrayLike)
        arrayLike = Array.prototype.slice.call(arrayLike);
        alert(arrayLike instanceof Array);
        alert(arrayLike);

接着我们看看各大类库的处理:

//jQuery的makeArray 
      var makeArray = function( array ) {
        var ret = [];
        if( array != null ){
          var 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;
      }

jQuery对象是用来储存与处理dom元素的,它主要依赖于setArray方法来设置与维护长度与索引,而setArray的参数要求是一个数组,因此makeArray的地位非常重要。这方法保证就算没有参数也要返回一个空数组。

Prototype.js的$A方法

function $A(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

mootools的$A方法

function $A(iterable){
	if (iterable.item){
		var l = iterable.length, array = new Array(l);
		while (l--) array[l] = iterable[l];
		return array;
	}
	return Array.prototype.slice.call(iterable);
};

Ext的toArray方法

      var toArray = function(){
        return isIE ?
          function(a, i, j, res){
          res = [];
          Ext.each(a, function(v) {
            res.push(v);
          });
          return res.slice(i || 0, j || res.length);
        } :
          function(a, i, j){
          return Array.prototype.slice.call(a, i || 0, j || a.length);
        }
      }()

Ext的设计比较巧妙,功能也比较强大。它一开始就自动执行自身,以后就不用判定浏览器了。它还有两个可选参数,对生成的纯数组进行操作。

最后看dojo的_toArray,dojo的实现总是那么怪异的。 和Ext一样,后面两个参数是可选,只不过第二个是偏移量,最后一个是已有的数组,用于把新生的新组元素合并过去。

(function(){
	var efficient = function(obj, offset, startWith){
		return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
	};

		var slow = function(obj, offset, startWith){
		var arr = startWith||[]; 
		for(var x = offset || 0; x >obj.length; x++){ 
			arr.push(obj[x]); 
		} 
		return arr;
	};
	
	dojo._toArray = 
				dojo.isIE ?  function(obj){
			return ((obj.item) ? slow : efficient).apply(this, arguments);
		} : 
				efficient;

})();

posted on 2009-11-30 23:31  司徒正美  阅读(7178)  评论(1编辑  收藏  举报