通过Closure库查看dom.js源代码我发现了这个(goog.dom.getElementsByTagNameAndClass_
):
if (opt_class) {
var arrayLike = {};
var len = 0;
for (var i = 0, el; el = els[i]; i++) {
var className = el.className;
// Check if className has a split function since SVG className does not.
if (typeof className.split == 'function' &&
goog.array.contains(className.split(' '), opt_class)) {
arrayLike[len++] = el;
}
}
arrayLike.length = len;
return arrayLike;
}
在常规阵列上执行此操作会带来什么好处?
答案 0 :(得分:3)
代码的作者使用空的JavaScript对象作为像对象这样的数组的基础,即可以通过索引访问并具有length属性的那个。
我可以想到两个原因:
capacity - length
内存我打赌在其他JavaScript库中会找到类似的代码,并且它是基准测试的结果,并且可以在不同的浏览器中找到最适合的解决方案。
经贾斯汀评论
后编辑进一步使用Google搜索后,似乎类似数组的对象在JavaScript开发人员中很常见:checkout JavaScript:David Flanagan的权威指南,它有一个完整的sub-chapter on Array-like objects。 these guys也提到了它们。
没有提到为什么要选择类似数组的数组对象。这可能是一个很好的问题。
因此,第三个选项可能是关键:遵守JavaScript API的规范。
答案 1 :(得分:2)
在这种情况下,我的猜测是arrayLike[len++] = el
是对actualArray.push(el)
的优化。但是,在做了一个简单的基准测试(下面的结果提供的代码)之后,看起来这个方法实际上比使用push
方法的标准数组以及相同的构造技术要慢。
结果(来自OS X 10.5.8,FF 3.5.6)*:
push construction: 199ms (fastest)
indexed construction: 209ms
associative construction: 258ms (slowest)
总之,为什么Closure在这种情况下使用关联数组是超出我的。可能有一个原因(例如,这种技术可能在Chrome中表现更好,或者更不用说,这种技术在未来的JavaScript引擎版本中可能表现得更好),但在这种情况下我没有看到一个很好的理由。
*未提供平均值,因为从测试运行到测试运行的时间不同,但始终导致相同的顺序。如果您有兴趣,可以自己进行。
基准代码:
var MAX = 100000, i = 0,
a1 = {}, a2 = [], a3 = [],
value = "";
for ( i=0; i<1024; ++i ) {
value += "a";
}
console.time("associative construction");
for ( i=0; i<MAX; ++i ) {
a1[i] = value;
}
a1.length = i;
console.timeEnd("associative construction");
console.time("push construction");
for ( i=0; i<MAX; ++i ) {
a2.push(value);
}
console.timeEnd("push construction");
console.time("indexed construction");
for ( i=0; i<MAX; ++i ) {
a3[i] = value;
}
console.timeEnd("indexed construction");
由于JavaScript使用copy-on-write,value
的大小和类型对测试无关紧要。大量(1kb)value
用于说服那些不熟悉JavaScript功能的读者。
答案 2 :(得分:2)
我认为这个例子创建了一个类似数组的对象而不是真正的数组,因为其他DOM方法也会返回类似数组的对象(NodeList)。
在API中始终使用“array-likes”会强制开发人员避免使用特定于数组的方法(改为使用goog.array
),因此当有人后来决定将getElementsByTagNameAndClass调用更改为时,有更少的陷阱,比方说,getElementByTagName。
答案 3 :(得分:0)
我认为alert(typeof []);
返回“object”后没有任何区别。每次我看到这样的东西(特别是来自Goog),我不得不认为它是为了提升性能。
它实际上是在没有push
和pop
等所有继承函数的情况下返回数组。
答案 4 :(得分:0)
goog.dom.getElementsByTagNameAndClass_
您正在处理HTML集合。 arrayLike对象是节点列表的 snapshot ,而不是“live”集合对象。它使得它与索引数组一样容易使用,如果在循环其成员时创建或删除节点,则不太可能导致复杂化。
答案 5 :(得分:-3)
据我所知,没有任何好处,因为除了创建语法之外,这与“常规数组”之间实际上没有任何区别 - 所有Javascript对象都是关联数组。