【问题标题】:Performance of jQuery selector with context带有上下文的 jQuery 选择器的性能
【发布时间】:2011-01-26 04:18:16
【问题描述】:

我正在阅读 Brandon Aaron here 的这篇文章,关于 jquery 上下文如何提供帮助。所以我想自己做一个测试。所以这就是我所做的。

  1. 在之前创建的“#context”中创建了一个 id="context" 的 DIV 和一个 id="holder" 的嵌套 DIV。

  2. 创建了一个深度为 18 的嵌套 DIV,并将 <div id="context"><div id="holder"></div></div> 附加到它上面,从而得到 20 个嵌套 DIV

  3. 现在我测试了通过以下选择器访问“#holder”所花费的时间:
    一种。 $("#holder") // no context
    湾。 $("#holder", "#context") // with "#context" selector string
    C。 $("#holder", $("#context")) // sending jquery object each time with selector "#context"
    d。 $("#holder", $context) // where, var $context = $("#context"). Caching jquery obj
    记录了访问X = 1000 次以及开始和结束时间差的每个案例。我发现花费的时间是:
    case(a) 是最不一致的 28-32 毫秒 [jquery-1.3.2]
    case(b)+(c) 的最高时间分别为 60-65 毫秒和 70-75 毫秒
    case(d) 有 40-50 毫秒,有 1 或 2 个尖峰值。

这种类型的基本检查有效吗?您可以在 JSBIN 使用 JS 代码here。 [如果我能以某种方式改进此测试,请告诉我]
如果是,那么这个“上下文”真的有什么帮助?


#NOTE:在 jsbin 编辑模式下也将 jquery-1.3.2 替换为 jquery-1.4.2,你会惊讶地看到数字上升:P

【问题讨论】:

  • 这是一个很好的发现。正如 Coronus 所说,对于 #id 选择器,您不应该传递上下文。但这就是原生和 jQuery 之间的差距。对于重复的 id,使用 document.getElementById() 将始终获得第一个匹配项。 $('#dupeId', '<selector>') 可以使第二个或多个具有重复 id 的元素可访问。

标签: jquery jquery-selectors performance


【解决方案1】:

当您正在搜索一个更大的 DOM 时,上下文确实很有帮助。搜索 ID 已经非常快了,在这种情况下,上下文并没有太大帮助。当您按标签名称或类别进行选择时,上下文真正可以发挥作用的地方。

尝试这样的测试:http://jsbin.com/aciji4/4

当您像这样增加 DOM 中的项目数量时,您确实可以看到上下文的时机变得更好:http://jsbin.com/aciji4/6

【讨论】:

  • 是的,这是有道理的。 select by id 本身高度优化,它是通过提供上下文进行优化的“选择器”的其他形式。顺便说一句,感谢 sn-p 更新,它真的很有帮助。
【解决方案2】:

使用上下文需要更长的时间(与单独使用选择器相比)是有道理的,因为在内部,上下文使用 .find() 方法,所以本质上,你真正要做的就是

$('#context').find('#holder');

我主要将其视为一种更简单的方法来识别上下文发生变化的事件和迭代器中的元素,因为

$('.holder', this)

$(this).find('.holder')

【讨论】:

  • 观察力不错。对于 ID,只要它们在页面上是唯一的(它们应该是,但可能不是),传递上下文会减慢速度。
【解决方案3】:

#ID 选择器依赖于浏览器原生 document.getElementById。无论如何它都会很快。

尝试使用 div.class[attribute=value] 之类的选择器,无论有无上下文。例如*,您可以使用此选择器选择右侧的“相关”问题链接:

// Selects anchor elements with href's beginning with /questions/
$('a[href^=/questions/]')

但是,限制选择器引擎必须迭代的锚元素数量会更快,评估相对昂贵的文本匹配:

$('a[href^=/questions/]', '.related')

* 为了讨论,忽略这些链接上明显更容易的 .question-hyperlink 类。

【讨论】:

    【解决方案4】:

    不管怎样,$context = $("#context") 仍在使用 jQuery 对象,然后必须将其转换为 DOM 对象。

    如果您使用$context = $("#context")[0],您会发现它的运行速度与第一次测试一样快。

    【讨论】:

      【解决方案5】:

      我已将 JSBin 代码放入 jsPerf Test

      $context.find('.holder') 的速度是其最接近的竞争对手 $('.holder', $context) 的 两倍,而且快了 十倍 比任何其他正在使用的选择器。

      总之,缓存你的选择器并使用 .find() 以获得最佳性能

      【讨论】:

        【解决方案6】:

        在重构代码之前要小心。正如#NOTE 所写,jQuery 自 1.4 以来的工作方式完全不同。最新版本可能包含更多优化。

        我修改了上面的 jsbin 代码以使用最新的 jQuery,并添加了一些额外的案例。您会看到,现在只有这三个 (2,3,6) 案例受到性能损失,每轮创建一个 jQuery 对象。休息在同一时间运行。

        你可以在这里找到修改后的版本:http://jsbin.com/aciji4/63/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-09
          • 2012-11-10
          • 2013-03-11
          • 1970-01-01
          • 1970-01-01
          • 2013-08-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多