比较$(“#foo .bar”)和$(“。bar”,“#foo”)的性能

时间:2011-12-22 02:19:21

标签: javascript jquery performance browser

向下滚动getById.getByClassNameqSA比较!


如果我们想要选择ID为"bar"的元素内的"foo"类的所有元素,我们可以这样写:

$( '#foo .bar' )

或者这个:

$( '.bar', '#foo' )

当然还有其他方法可以达到这个目的,但是为了这个问题,让我们只比较这两种方法。

那么,上述哪种方法表现更好? (这需要更少的时间来执行?)

我写了这个性能测试:

(function() {
    var i;

    console.time('test1');
    for( i = 0; i < 100; i++ ) {
        $('#question-mini-list .tags');
    }
    console.timeEnd('test1');

    console.time('test2');
    for( i = 0; i < 100; i++ ) {
        $('.tags', '#question-mini-list');
    }
    console.timeEnd('test2');
})();

您必须在 Stack Overflow start-page 的控制台内执行它。我的结果是:

火狐:
test1:~90ms
test2:~18ms

铬:
test1:~65ms
test2:~30ms

歌剧:
test1:~50ms
test2:~100ms

所以在Firefox和Chrome中,第二种方法的速度要快很多倍 - 就像我预期的那样。然而,在Opera中,情况正好相反。我想知道这里发生了什么。

您能否在您的机器上运行测试并解释为什么Opera的表现不同?


更新

我写过这个测试,以便调查Opera的qSA是否真的超级快。事实证明,它是。

(function() {
    var i, limit = 5000, test1 = 'test1', test2 = 'test2';

    console.time( test1 );
    for( i = 0; i < limit; i += 1 ) {
        document.getElementById( 'question-mini-list' ).getElementsByClassName( 'tags' );
    }
    console.timeEnd( test1 );

    console.time( test2 );
    for( i = 0; i < limit; i += 1 ) {
        document.querySelectorAll( '#question-mini-list .tags' );
    }
    console.timeEnd( test2 );
})();

同样,您必须在Stack Overflow开始页面的控制台中运行此代码。我使用了针对IE9的Firebug Lite书签(因为该浏览器没有实现console.time)。

所以,我比较了这种方法:

document.getelementById( 'A' ).getElementsByClassName( 'B' );

这个方法:

document.querySelectorAll( '#A .B' );

我在每个浏览器中连续五次执行上面的脚本。算术手段是:

enter image description here

(所有数字均以毫秒为单位。)

因此,第一种方法的性能在测试的浏览器中几乎相同(16-36ms)。然而,虽然qSA与第一种方法相比要慢得多,但在Opera中它实际上更快!

所以,qSA优化是可能的,我想知道其他浏览器在等什么......

3 个答案:

答案 0 :(得分:3)

如果浏览器支持querySelectorAll,并且传递了有效的选择器(没有自定义的非CSS选择器),jQuery / Sizzle将避免使用基于JavaScript的Sizzle引擎。

这意味着您最终要比较querySelectorAll的实现,假设您正在测试支持它的浏览器。

还有jQuery或Sizzle使用的其他优化,因此在不同浏览器中比较不同类型的DOM选择时,这很棘手。

Opera的性能结果似乎是因为它们具有非常高度优化的querySelectorAll实现。 qSA是一种相对较新的方法,与getElementsByTagName等旧方法相比,在某些浏览器中并未得到优化。

答案 1 :(得分:1)

获胜者是......

测试3 $('#question-mini-list').find('.tags');

  • test1:25ms
  • test2:19ms
  • test3:10ms

您建议的两种方法不相同。

测试1 :Sizzle从右到左解析(不要求它在页面上搜索任何元素,然后限制为ID)。

测试2 :使用字符串作为上下文通常没有用,请使用元素作为上下文。

测试3 :查找带有id的元素非常快。一旦你在那里,就可以轻松地专注于某个特定类的项目。

答案 2 :(得分:1)

作为参考,速度提高了30倍:

document.getElementById("foo").getElementsByClassName("bar");

参见jsPerf:http://jsperf.com/jquery-selector-variations/3。这需要垫片才能在旧版IE中使用。

虽然jQuery非常有用,但如果速度最快,那么它并不总是最适合这项工作的工具。