1.3 数组化
浏览器下存在许多类数组对象,如function内的arguments,通过document.forms、form. elements、doucment.links、select.options、document.getElementsByName、document.getElementsBy TagName、childNodes、children等方式获取的节点集合(HTMLCollection、NodeList),或依照某些特殊写法的自定义对象。
var arrayLike = {
0: "a",
1: "1",
2: "2",
length: 3
}
类数组对象是一个很好的存储结构,不过功能太弱了,为了享受纯数组的那些便捷方法,我们在处理它们前都会做一下转换。
通常来说,只要[].slice.call就能转换了,但旧版本IE下的HTMLCollection、NodeList不是Object的子类,采用如上方法将导致 IE 执行异常。我们看一下各大库怎么处理的。
//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() {
returnisIE ?
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和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]);
}
returnarr;
};
dojo._toArray =
dojo.isIE ? function(obj) {
return ((obj.item) ? slow : efficient).apply(this, arguments);
} :
efficient;
})();
最后是mass的实现,与dojo一样,一开始就进行区分,W3C方直接[].slice.call,IE自己手动实现一个slice方法。
$.slice = window.dispatchEvent ? function(nodes, start, end) {
return [].slice.call(nodes, start, end);
} : function(nodes, start, end) {
var ret = [],
n = nodes.length;
if (end === void 0 || typeof end === "number" && isFinite(end)) {
start = parseInt(start, 10) || 0;
end = end == void 0 ? n : parseInt(end, 10);
if (start < 0) {
start += n;
}
if (end > n) {
end = n;
}
if (end < 0) {
end += n;
}
for (var i = start; i < end; ++i) {
ret[i - start] = nodes[i];
}
}
return ret;
}
时间: 2025-01-31 01:44:43