【问题标题】:Good ways to improve jQuery selector performance?提高 jQuery 选择器性能的好方法?
【发布时间】:2010-09-07 22:54:59
【问题描述】:

我正在寻找可以提高 jQuery 调用的选择器性能的任何方法。具体是这样的:

$("div.myclass")$(".myclass")

我想可能是这样,但我不知道 jQuery 是否足够聪明,可以先通过标签名称限制搜索,等等。有人对如何制定 jQuery 选择器字符串以获得最佳性能有任何想法吗?

【问题讨论】:

    标签: javascript jquery performance css-selectors


    【解决方案1】:

    毫无疑问,先按标签名过滤比按类名过滤要快得多

    在所有浏览器都本地实现 getElementsByClassName 之前,情况都会如此,就像 getElementsByTagName 的情况一样。

    【讨论】:

    • 但是即使浏览器实现了该功能,按标签名称过滤仍然会更快,对吧?
    • 我已经从 Jeffs 的回复中更新了componenthouse.com/article-19 以使用最新的 jQuery,从第二次测试来看,似乎 A 和 B 在 Opera 10 和 firefox 3.5 中具有相同的性能。我无法让它在 IE8 上运行(虽然我没有尝试太多)。所以看来我之前的评论是错的。
    • @hoffmann,可能不是。如果我们假设这两个函数都是用 b-trees 实现的,我不明白为什么 getElementsByClassName 会更慢......您仍然必须在能够使用该函数之前构建索引......
    • @AlienWebguy:这个答案的重点是某些浏览器不支持getElementsByClassName,这意味着页面上的每个元素都需要针对该类进行测试.请记住,这个答案也是在 08 年给出的。 ;o)
    • @AlienWebguy:您的测试不能准确地表示包含许多 DOM 元素的大页面。借助更简单的过滤器集,而不是更快的查找,您的测试更快。
    【解决方案2】:

    在某些情况下,您可以通过限制上下文来加快查询速度。如果您有元素引用,则可以将其作为第二个参数传递以限制查询范围:

    $(".myclass", a_DOM_element);
    

    应该比

    $(".myclass");
    

    如果您已经有一个 _DOM_element 并且它比整个文档小得多。

    【讨论】:

    • 我记得$('.myclass', a_DOM_element) jQuery 转换为/调用$(a_DOM_element).find('.myclass') 所以它可能简单地使用find() 而不是建立一个selector context 稍微快一点在你的第一个例子中。
    【解决方案3】:

    正如 Reid 上面所说的,jQuery 是自下而上工作的。虽然

    这意味着$('#foo bar div') 是一个 比$('bar div #foo')慢很多

    这不是重点。如果您有 #foo,则无论如何都不会在选择器中添加任何内容,因为 ID 必须是唯一的。

    重点是:

    • 如果您从具有 ID 的元素中选择任何内容,请先选择后者,然后使用 .find.children 等:$('#foo').find('div')
    • 选择器的最左边(第一)部分可以缩放到最右边(最后)部分的效率较低,应该是最有效的 - 意思是如果你不这样做'没有 ID 确保您正在寻找 $('div.common[slow*=Search] input.rare') 而不是 $('div.rare input.common[name*=slowSearch]') - 因为这并不总是适用,请确保通过相应拆分来强制选择器顺序。

    【讨论】:

      【解决方案4】:

      为了完全理解什么是更快,您必须了解 CSS 解析器的工作原理。

      您传入的选择器会使用 RegExp 拆分为可识别的部分,然后逐个处理。

      一些选择器,如 ID 和 TagName,使用浏览器的本地实现,速度更快。而其他像类和属性是分开编程的,因此速度要慢得多,需要遍历选定的元素并检查每个类名。

      所以可以回答你的问题:

      $('tag.class') 比 $('.class') 更快。为什么? 对于第一种情况,jQuery 使用本机浏览器实现将选择过滤到您需要的元素。只有这样,它才会启动较慢的 .class 实现,过滤到您要求的内容。

      在第二种情况下,jQuery 使用它的方法通过抓取类来过滤每个元素。

      这比 jQuery 传播得更远,因为所有 javascript 库都基于此。唯一的其他选择是使用 xPath,但目前所有浏览器都不太支持它。

      【讨论】:

        【解决方案5】:

        以下是提高 jQuery 选择器性能的方法:

        【讨论】:

          【解决方案6】:

          我要补充一点,在 99% 的网络应用程序中,即使是 ajax 重度应用程序,网络服务器的连接速度和响应将推动应用程序的性能,而不是 javascript。我并不是说您应该故意编写慢代码,或者通常意识到哪些事情可能比其他事情更快是不好的。

          但我想知道您是否正在尝试解决一个尚不存在的问题,或者即使您正在针对在不久的将来可能更改的某些内容进行优化(例如,如果更多的人开始使用支持前面提到的getElementsByClassName() 功能的浏览器),那么您的优化代码实际上会运行得更慢。

          【讨论】:

            【解决方案7】:

            另一个查找性能信息的地方是 Hugo Vidal Teixeira 的选择器性能分析页面。

            http://www.componenthouse.com/article-19

            这可以很好地降低按 id 选择器、按类选择器和选择器前缀标记名称的速度。

            id 最快的选择器是:$("#id")

            按类别最快的选择器是:$('tag.class')

            因此,只有在按类别选择时,才能使用标签前缀!

            【讨论】:

              【解决方案8】:

              我一直在一些 jQuery 邮件列表中,从我在那里读到的内容来看,它们很可能按标签名称然后类名称过滤(反之亦然,如果它更快的话)。他们对速度非常着迷,并且会使用任何东西来获得一点性能。

              除非您每秒运行该选择器数千次,否则我真的不会太担心它。

              如果您真的很担心,请尝试做一些基准测试,看看哪个更快。

              【讨论】:

                【解决方案9】:

                考虑使用 Oliver Steele 的 Sequentially 库随时间调用方法,而不是一次调用所有方法。

                http://osteele.com/sources/javascript/sequentially/

                “最终”方法可帮助您在从初始调用开始的一段时间后调用方法。 “顺序”方法让您可以在一段时间内对多个任务进行排队。

                很有帮助!

                【讨论】:

                  【解决方案10】:

                  great tip 来自我提出的一个问题:尽可能使用标准 CSS 选择器。这允许 jQuery 使用Selectors API。根据tests performed by John Resig,这导致选择器的性能接近原生。应避免使用:has():contains() 等函数。

                  根据我的研究,jQuery 1.2.7、Firefox 3.1、IE 8、Opera 10、Safari 3.1 引入了对 Selectors API 的支持。

                  【讨论】:

                    【解决方案11】:

                    如果我没记错的话,jQuery 也是一个自下而上的引擎。这意味着$('#foo bar div')$('bar div #foo') 慢很多。例如,$('#foo a') 将遍历页面上的所有a 元素,看看它们是否有#foo 的祖先,这使得这个选择器非常低效。

                    Resig 可能已经针对这种情况进行了优化(如果他这样做了,我不会感到惊讶 - 我相信他在他的 Sizzle 引擎中做到了,但我不是 100% 确定。)

                    【讨论】:

                      【解决方案12】:

                      我相信先按 ID 选择总是更快:

                      $("#myform th").css("color","red");
                      

                      应该比

                      $("th").css("color","red");
                      

                      但是,我想知道以 ID 开头的链接有多大帮助?这是吗

                      $("#myform").find("th").css("color","red")
                      .end().find("td").css("color","blue");
                      

                      比这更快吗?

                      $("#myform th").css("color","red");
                      $("#myform td").css("color","blue");
                      

                      【讨论】:

                      • 根据我的经验,$("#myform").find("th") 也比 $("#myform th") 快,因为前者直接委托给浏览器的本机 getElementByID。链接也有帮助,但基本上开销是第二次 getElementByID 调用的成本,这通常很小。
                      • 嘶嘶声,jQuery 的选择器引擎从右到左工作。所以你的第一个例子: $("#myform th").css("color","re​​d");首先找到页面上的每一个。然后它遍历这些 th 并查看每个父级,直到找到一个 ID 为 myForm 的元素。理论上你的第二个例子: $("th").css("color","re​​d");应该比你的第一个更快,因为这只是迭代 th 而不是检查他们的父母。
                      猜你喜欢
                      • 2015-12-05
                      • 2013-06-13
                      • 1970-01-01
                      • 2020-03-02
                      • 2019-09-06
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-11-27
                      • 2011-06-23
                      相关资源
                      最近更新 更多