像JavaScript中的对象

通过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;
}

在常规数组上做这件事会有什么好处?


代码的作者使用空的JavaScript对象作为像对象这样的数组的基础,即可以通过索引访问并具有长度属性的对象。

我可以想到两个原因:

  • 内存使用 - 如果数组由支持分配n个元素的实现支持,当达到它的限制时,它会通过某种因素增长以增加其容量,从而浪费capacity - length内存的capacity - length
  • CPU时间 - 实现者选择插入速度超过随机访问速度 - 这种方法的返回更有可能被顺序迭代而不是随机访问,并且在插入时调整数组的大小会导致具有CPU惩罚的分配 - 复制 - 解除分配
  • 我敢打赌,在其他JavaScript库中可以找到类似的代码,并且它是基准测试的结果,并在不同浏览器中找到最适合的解决方案。

    贾斯汀评论后编辑

    在进一步的Google搜索中,似乎类似于数组的对象在JavaScript开发人员中很常见:checkout JavaScript:David Flanagan的权威指南,它有关于类似Array的对象的整个子章节。 这些人也提到他们。

    没有提到为什么应该更喜欢类似数组的对象。 这可能是一个很好的SO问题。

    所以第三个选择可能是关键:符合JavaScript API的规范。


    在这种情况下,我的猜测是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");
    

    value的大小和类型对于测试来说是微不足道的,因为JavaScript使用了写入时复制。 为了说服那些不熟悉JavaScript这一特性的读者,使用了一个大的(1kb) value


    我认为这个例子创建了一个类似数组的对象,而不是一个真正的数组,因为其他的DOM方法也返回数组类对象(NodeList)。

    在API中一直使用“数组 - goog.array ”迫使开发人员避免使用特定于数组的方法(使用goog.array代替),因此当稍后某人决定将getElementsByTagNameAndClass调用更改为getElementByTagName时,会出现更少的陷阱。

    链接地址: http://www.djcxy.com/p/43967.html

    上一篇: like object in javascript

    下一篇: Dropdown currentIndex onchange