【问题标题】:In jQuery, is selecting by class or id faster than selecting by some other attribute?在 jQuery 中,按类或 id 选择是否比按其他属性选择更快?
【发布时间】:2011-09-21 14:01:32
【问题描述】:

基本上是

$("#someid")

$(".someclass")

快于

$("[someattr='value']")

我想是这样的(也就是说,按 id 选择最快,然后是类,然后是属性),但是有人确定吗?

【问题讨论】:

  • 不像大家想的那样非黑即白:jsperf.com/attribute-vs-class-selection/3 类与属性看起来并驾齐驱。
  • 当我测试我的页面时,我很惊讶(并做出了假设)——我发现一些选择结构不如我的实际页面上的其他结构那样高效。我现在测试更多:)
  • 我正要问同样的问题,你节省了我一些时间。

标签: javascript jquery jquery-selectors


【解决方案1】:

ID 绝对是最快的。部分原因是 ID 应该是唯一的,所以 API 在 DOM 中找到 ID 后停止搜索。

如果必须使用类或属性选择器,可以通过指定可选的上下文参数来提高性能。

例如...

$(".someclass", "#somecontainer")

somecontainer 类似于一个 div,围绕着一个类为 someclass 的元素。在somecontainer 只包含一小部分 DOM 的情况下,这可以提供巨大的性能优势。


更新:

几年前我围绕上下文参数做了一些测试。在阅读了下面的 cmets 之后,我很好奇是否有任何变化。事实上,现在的浏览器似乎已经改变了一些情况。也许它也与 jQuery 的改进有关?我不知道。

这是我的 10,000 次迭代的结果(代码如下):

IE9

$(".someclass") - 2793 毫秒

$(".someclass", "#somecontainer") - 1481 毫秒

Chrome 12

$(".someclass") - 75 毫秒

$(".someclass", "#somecontainer") - 104 毫秒

Firefox 3.6

$(".someclass") - 308 毫秒

$(".someclass", "#somecontainer") - 357 毫秒

所以在这三大现代浏览器中,context 参数似乎只对 IE9 有帮助。较旧的浏览器也将从上下文参数中受益。但考虑到这些浏览器中的每一个的普及率并平均所有内容,现在的净收益有点被洗掉了。

这是代码,以防有人想自己尝试......

<html>
    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function(){

                startTime = new Date().getTime();               
                for (i = 0; i < 10000; i++)
                {
                    s = $(".someclass");
                }           
                $("#withoutcontext").html(elapsedMilliseconds(startTime));


                startTime = new Date().getTime();
                for (i = 0; i < 10000; i++)
                {
                    s = $(".someclass", "#somecontainer");
                }           
                $("#withcontext").html(elapsedMilliseconds(startTime));

            });

            function elapsedMilliseconds(startTime)
            {
                var n = new Date();
                var s = n.getTime();
                var diff = s - startTime;
                return diff;
            }
        </script>
    </head>
    <body>
        <h1>jQuery Selector Performance: Context vs No Context</h1>

        <h2>$(".someclass")</h2>
        <span id="withoutcontext">---</span> ms<br /><br />

        <h2>$(".someclass", "#somecontainer")</h2>
        <span id="withcontext">---</span> ms<br /><br />

        <hr />

        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <div id="somecontainer">
            <p class="a">a</p>
            <p class="b">b</p>
            <p class="c">c</p>
            <p class="someclass">someclass</p>
        </div>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
    </body>
</html>

【讨论】:

  • 如果我想要该类的每个元素,无论它位于何处,该怎么办? (更现实地说,body 中的每个这样的元素,但解决方案是向body 添加一个 ID 吗?)
  • 然后去掉上下文参数。我只是提到它,因为我觉得它经常被遗忘。我没有在身体上测试过身份证,但我认为这不会有太大帮助。
  • 我实际上在一些复杂的页面中发现,class-within-a-div 假设并不总是正确的,因为它的性能最高。
  • @Mark - 哇。你说得对。令人惊讶的是,事情在几年内发生了怎样的变化。你可以在上面看到我的结果。
  • @Steve Wortham:感谢测试。
【解决方案2】:

通过ID选择是最快的,因为直接映射到getElementByID,另外2个要检查每个元素才能确定选择的元素。

如果您必须使用类或属性进行选择,请尝试将搜索包含在 ID 中。 例如。

$("#someid .someclass")

【讨论】:

  • 我想这部分是正确的,但是按类选择也会映射到 getElementsByClassName 对吗?
  • 实际上,#id .class 语法没有帮助。如果您想要任何性能优势,您应该使用可选的上下文参数。
  • 是的,它映射到 getElementsByClassName,但不在 IE6-8 中。 Firefox、Opera、Safari 和 Chrome 都支持它。
  • 这绝对是正确的答案,因为它利用了 querySelectorAll() 方法的使用,并且比 $(".someclass", "#somecontainer") 快得多
【解决方案3】:

ID 是唯一的,如果您只想在此处选择一个/第一个元素,则等效

$("#someid") => 75,695 ops/sec,最快

$(.unique_class') => 45,257 ops/sec,慢 40%:页面上只有一个类

$(".someclass").first() => 42,217 ops/sec,慢 46%:页面上有多个类,选择第一个元素

$(".someclass:eq(0)") => 18,324 ops/sec,慢 76%:页面上有多个类,在选定索引处选择元素

测试网址:http://jsperf.com/jquery-selector-speed-tests/98

【讨论】:

    【解决方案4】:

    ID 和类选择器,至少在它们自己使用时,往往更快,无论是 jQuery 还是 CSS。这主要是因为浏览器在其 DOM/CSS 引擎中针对 ID 和类优化了算法。

    在具有最新版本 jQuery 的现代浏览器中,任何被浏览器理解为支持的 CSS 选择器的选择器字符串都将由 document.querySelectorAll() 处理,只要使用标准 CSS 选择器,就可以提供最佳性能。非标准选择器或旧版浏览器由 jQuery 和/或 Sizzle 库处理,它们尽最大努力利用 DOM 的 get-element(s) 方法来遍历 DOM。

    要记住的最重要的事情是,由于不同的 DOM 实现,性能会因浏览器(版本)而异。至少,我认为事情是这样的。

    【讨论】:

    • 现代浏览器是 IE 8+、Chrome、Safari、Firefox。因此,任何非业务要求的浏览器。
    • 对于 css 的属性选择也很重要(因为有属性选择器)所以它也是优化的。
    【解决方案5】:

    id 总是最快的,因为它在页面上是唯一的。类“可能”比属性快,但这取决于。

    这里真正的关键是在其中选择一个类,ID 可能不会比仅仅选择类更快。这将取决于页面和浏览器。在我的测试中,选择一个复杂页面,其中包含有限数量的元素和一个“类”,其中类元素的父级具有如下 id:

    <div id='iamout'>
      <div class='aonther'>
        <div class='iamin'>stuff</div>
        <div class='iamin'>stuff</div>
      </div>
    </div>
    

    $('.iamin','#iamout') 之类的选择器并不总是像 $('.iamin') 一样快

    并非所有浏览器都支持按类名选择(本机),但现代/较新的浏览器支持,因此它可能会根据您使用的浏览器提供更好的性能。

    如果您需要获得最佳性能,则需要测试您的确切页面。

    【讨论】:

      【解决方案6】:

      Id 最快,因为它是唯一可以具有该标识符的元素。许多对象可能具有相同的类名。有人可以验证这一点,但是一旦找到 id,似乎就不需要再遍历文档了。对于班级,情况可能并非如此?高温

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-29
        • 1970-01-01
        • 2015-10-18
        • 1970-01-01
        • 1970-01-01
        • 2012-09-11
        • 1970-01-01
        • 2015-12-28
        相关资源
        最近更新 更多