0

假设我的页面上有以下 JS(compare是一个与问题无关的简单比较器函数):

    function sortArray(a) {
        a.sort(compare);
    }

    function sortJQuerySet(b) {
        b.sort(compare);
    }

    $(document).ready(function(){
        var a = [], b = [], i = 0, n = 1000;

        for(i=0; i<n; ++i) {
            a.push($('<div>' + i.toString() + '</div>'));
            b.push($('<div>' + i.toString() + '</div>'));
        }

        b = $(b);

        $('#runner').click(function(){
            sortArray(a);
            sortJQuerySet(b);
        });
    });

可以看到,ab本质上都是同一个数组,唯一的区别就是b变成了jQuery set. 我正在尝试对这两个数组进行排序并分析排序。请注意,两个数组中的元素数均为 1000。

以下是 Safari 中两个容器的排序分析结果: 在此处输入图像描述

Safari 对包含 1000 个元素的 jQuery 集进行了大约50 万次比较。这看起来更像二次排序而不是O(n log n)排序。同时,对原生数组进行排序就可以了。

Chrome 浏览器中的排序对两种容器类型的工作时间大致相同。

PS 我使用 Safari 6.0.4、jQuery 1.7.1 和 jQuery 1.10.1。代码:https ://gist.github.com/ikostia/5925715

4

1 回答 1

1

也许这个关于 WebKit 引擎的讨论可以提供一些启示。

在我看来,从这条线: 631 if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->inSparseMode()) { 仅非数组,或某种“稀疏”中的数组" 模式排序效率低。我不确定什么是稀疏模式,但让我们试试我的 Raymond Chen 启发的精神力量:如果你指定 a[0]=1 和 a[1000000]=2,你不希望存储 1 到 999999,所以像这样的数组最终会以稀疏模式结束,它的功能更像是一个以整数为键的哈希表。这同样适用于非数组......

(上述引用中讨论的源代码在这里

所以现在让我们看一下jQuery 源代码。调用$(someArrayOrSelectorString)导致调用init方法(第 43 行)。init 方法返回jQuery.makeArray( selector, this ),其中this是 jQuery 的一个实例(如果我错了,请纠正我)。最后,调用内部makeArray方法jQuery.merge(第 600 行),它将使用传递的数组元素填充 jQuery 实例。

所以看起来包装一个数组会产生一个类似数组的对象(jQuery实例),但不是一个真正的数组。Safari 将这个对象视为稀疏对象。

(您可能对此答案和评论感兴趣。这就是我借用这个想法来回答的地方)

于 2013-07-09T10:11:12.840 回答