简体   繁体   English

javascript中类似数组的对象

[英]Array-like object in javascript

Looking through the dom.js source from the Closure library I found this (in goog.dom.getElementsByTagNameAndClass_ ): 通过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;
}

What would be the benefit of doing this over a regular array? 在常规阵列上执行此操作会有什么好处?

The author of the code used empty JavaScript object as a basis of a array like object, ie the one that can be accessed by index and has a length property. 代码的作者使用空的JavaScript对象作为像对象一样的数组的基础,即可以通过索引访问并具有length属性的数组。

There could be two reasons that I could think of: 我可以想到两个原因:

  1. memory use - if array is backed by implementation that allocates n elements, when it reaches it's limits it grows by some factor to increase it's capacity, and thusly wastes capacity - length of memory 内存使用 - 如果数组由分配n个元素的实现支持,当它达到它的限制时,它会增加一些因素来增加它的容量,从而浪费capacity - length内存capacity - length
  2. cpu time - implementor choose insertion speed over random access speed -- a return from this method is more likely to be iterated over sequentially than random accessed, and resizing the array in insertion causes allocation-copy-deallocation which has a cpu penalty cpu time - 实现者选择插入速度超过随机访问速度 - 这种方法的返回更有可能比随机访问顺序迭代,并且在插入时调整数组大小会导致具有cpu惩罚的分配复制释放

I'm betting that similar code would be found in other JavaScript libraries, and that it's result of benchmarking and finding the best to fit solution across different browsers. 我敢打赌,在其他JavaScript库中可以找到类似的代码,并且它是基准测试的结果,并且可以在不同的浏览器中找到最适合的解决方案。

edited after comment by Justin 贾斯汀评论后编辑

Upon further googling it appears that array-like objects are common among JavaScript developers: checkout JavaScript: the definitive guide by David Flanagan, it has a whole sub-chapter on Array-like objects . 进一步谷歌搜索后,似乎类似数组的对象在JavaScript开发人员中很常见:checkout JavaScript:David Flanagan的权威指南,它有一个关于类似Array的对象的完整子章节 Also these guys mention them. 这些 家伙也提到了他们。

No mention of why should one prefer array-like vs array object. 没有提到为什么一个人更喜欢类似数组的数组对象。 This could be a good SO question. 这可能是一个很好的问题。

So a third option could be the key: compliance with norms of JavaScript API's. 所以第三种选择可能是关键:遵守JavaScript API的规范。

In this case, my guess would be that arrayLike[len++] = el is an optimization over actualArray.push(el) . 在这种情况下,我的猜测是arrayLike[len++] = el是对actualArray.push(el)的优化。 However, after doing a simple benchmark (code provided below results), it appears that this method is actually slower than using a standard array using the push method as well as with same construction technique. 但是,在做了一个简单的基准测试(下面提供的代码结果)之后,看起来这个方法实际上比使用push方法的标准数组以及相同的构造技术慢。

Results (from OS X 10.5.8, FF 3.5.6) *: 结果(来自OS X 10.5.8,FF 3.5.6)*:

push construction:        199ms (fastest)
indexed construction:     209ms
associative construction: 258ms (slowest)

In conclusion, why Closure is using an associative array in this case is beyond me. 总之,为什么Closure在这种情况下使用关联数组是超出我的。 There may likely be a reason (for instance, this technique may perform better in Chrome, or less dubiously, this technique may perform better in future releases of JavaScript engines in general), but I don't see a good reason in this case. 可能有一个原因(例如,这种技术可能在Chrome中表现更好,或者更不用说,这种技术在未来的JavaScript引擎版本中可能表现得更好),但在这种情况下我没有看到一个很好的理由。

* A mean was not provided because the times varied from test run to test run, but consistently resulted in the same order. *未提供平均值,因为从测试运行到测试运行的时间不同,但始终导致相同的顺序。 If you're interested, you can carry it out on your own. 如果您有兴趣,可以自己进行。

Benchmark code: 基准代码:

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");

The size and type of value is insignificant to the test as JavaScript uses copy-on-write . 由于JavaScript使用copy-on-write ,因此value的大小和类型对测试无关紧要。 A large (1kb) value was used for the purpose of convincing those readers who are not familiar with this feature of JavaScript. 使用大(1kb) value来说服那些不熟悉JavaScript功能的读者。

I think this example creates an array-like object instead of a real array, because other DOM methods also return array-like objects (NodeList). 我认为这个例子创建了一个类似于数组的对象而不是真正的数组,因为其他DOM方法也返回类似数组的对象(NodeList)。

Consistently using "array-likes" in the API forces the developer to avoid using the array-specific methods (using goog.array instead), so there are fewer gotchas when someone later decides to change a getElementsByTagNameAndClass call to, say, getElementByTagName. 在API中goog.array使用“array-likes”会强制开发人员避免使用特定于数组的方法(改为使用goog.array ),因此当有人后来决定将getElementsByTagNameAndClass调用更改为getElementByTagName时,问题就会减少。

I don't see any difference since alert(typeof []); 我没有看到任何alert(typeof []); returns "object". 返回“对象”。 Any time I see something like this (especially from the Goog), I have to assume it is for a boost in performance. 每次我看到这样的东西(特别是来自Goog),我必须假设它是为了提升性能。

It is essentially returining an array without all of the inherited functions such as push and pop . 它本质上是在没有所有继承函数(如pushpop情况下返回数组。

goog.dom.getElementsByTagNameAndClass_

You are dealing with html collections. 你正在处理HTML集合。 An arrayLike object is a snapshot of a node list, rather than the 'live' collection object. arrayLike对象是节点列表的快照 ,而不是“实时”集合对象。 It makes it as easy as an indexed array to work with, and less likely to cause complications if you create or delete nodes while looping through its members. 它使得它与索引数组一样容易使用,如果在循环其成员时创建或删除节点,则不太可能导致复杂化。

据我所知,没有任何好处,因为除了创建语法之外,这与“常规数组”之间实际上没有任何区别 - 所有Javascript对象都是关联数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM