【问题标题】:What is the fastest method for selecting descendant elements in jQuery?在 jQuery 中选择后代元素的最快方法是什么?
【发布时间】:2011-03-11 19:16:39
【问题描述】:

据我所知,jQuery中有多种选择子元素的方法。

//Store parent in a variable  
var $parent = $("#parent");

方法一 (通过使用范围)

$(".child", $parent).show();

方法二 (find()方法)

$parent.find(".child").show();

方法 3 (仅限直系子女)

$parent.children(".child").show();

方法 4 (通过 CSS 选择器) - @spinon 建议

$("#parent > .child").show();

方法5 (与方法2相同) - 根据@Kai

$("#parent .child").show();

我不熟悉能够自己调查此问题的分析,所以我很想看看你有什么要说的。

附:我知道这可能与 this question 重复,但它并未涵盖所有方法。

【问题讨论】:

  • 另外,@spinon - 仅适用于直系子女吗? CSS 规范说“匹配作为元素 E 的子元素的任何 F 元素。”
  • 你不必担心哪个更快(除非你正在做一个非常大的 dom 操作)...... jQuery 的构建速度非常快......
  • 我有一个 2MB 的 HTML 文件,不要问如何或为什么 :)
  • 是的。仅限第一级后代。
  • 还有一种方法。 $("#parent .child").show();这与 #2 的方式相同。 :)

标签: jquery performance jquery-selectors profiling


【解决方案1】:

方法1方法2相同,唯一不同的是方法1需要解析传递的作用域并将其翻译成致电$parent.find(".child").show();

方法4方法5都需要解析选择器,然后分别调用:$('#parent').children().filter('.child')$('#parent').filter('.child')

所以方法3总是最快的,因为它需要做的工作最少,用最直接的方法得到一级子。

基于 Anurag 在此处修改的速度测试:http://jsfiddle.net/QLV9y/1/

速度测试:(越多越好)

Chrome 上,方法 3 最好,然后是方法 1/2,然后是 4/5

Firefox 上,方法 3 仍然最好,然后是方法 1/2,然后是 4/5

Opera 上,方法 3 仍然最好,然后是方法 4/5,然后是 1/2

IE 8 上,虽然总体上比其他浏览器慢,但它仍然遵循方法 3,1,2,4,5 排序。

总体而言,方法 3 是整体上最好的方法,因为它是直接调用的,与方法 1/2 不同,它不需要遍历多于一层的子元素,而且它不需要t 需要像方法 4/5 那样解析

不过,请记住,在其中一些方法中,我们将苹果与橙子进行比较,因为方法 5 着眼于所有儿童而不是第一级儿童。

【讨论】:

  • 相同的意思是他们都使用相同的逻辑进行搜索?
  • 你不是说方法1和方法2是一样的吗?
  • 谢谢@Aaron - 我想看看其他人的想法,如果每个人都同意,我会接受你的回答。干杯:)
  • @J-P,我的意思是它需要花费额外的时间来识别正在传递的范围以将其转换为 $parent.find(".child"); 命令。
  • @Aaron @Marko - 测试可能有点偏差,因为我们总是使用根节点作为上下文,而且文档很大。尽管如此,在大多数运行中,我看到 1 和 2 在 20 ops/sec 内相互排列。与 1 和 2 相比,4 慢了大约 100-200 ops,而 5 慢了大约 400 ops,这是可以理解的,因为它通过所有后代而不仅仅是孩子。图表 - tinyurl.com/25p4dhq
【解决方案2】:

因为这是一个旧帖子,并且事情会随着时间而变化。到目前为止,我对最新的浏览器版本进行了一些测试,并将其发布在此处以避免误解。

在兼容 HTML5 和 CSS3 的浏览器上使用 jQuery 2.1 会改变性能。

这里是测试场景和结果:

function doTest(selectorCallback) {
    var iterations = 100000;

    // Record the starting time, in UTC milliseconds.
    var start = new Date().getTime();

    for (var i = 0; i < iterations; i++) {
        // Execute the selector. The result does not need to be used or assigned
        selectorCallback();
    }

    // Determine how many milliseconds elapsed and return
    return new Date().getTime() - start;
}

function start() {
    jQuery('#stats').html('Testing...');
    var results = '';

    results += "$('#parent .child'): " + doTest(function() { jQuery('#parent .child'); }) + "ms";
    results += "<br/>$('#parent > .child'): " + doTest(function() { jQuery('#parent > .child'); }) + "ms";
    results += "<br/>$('#parent').children('.child'): " + doTest(function() { jQuery('#parent').children('.child'); }) + "ms";
    results += "<br/>$('#parent').find('.child'): " + doTest(function() { jQuery('#parent').find('.child'); }) + "ms";
    $parent = jQuery('#parent');
    results += "<br/>$parent.find('.child'): " + doTest(function() { $parent.find('.child'); }) + "ms";

    jQuery('#stats').html(results);
}
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=7, IE=8, IE=9, chrome=1" />
    <title>HTML5 test</title>
    <script src="//code.jquery.com/jquery-2.1.1.js"></script>
</head>
<body>

<div id="stats"></div>
<button onclick="start()">Test</button>

<div>
    <div id="parent">
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
    </div>
</div>

</body>
</html>

所以,对于 100 000 次迭代,我得到:

(出于格式化目的,我已将它们添加为 img。)

你可以自己运行代码sn-p来测试;)

【讨论】:

  • 哦!然后看起来.find() 做得很好。继续使用它。 :)
  • 我在 Android webview 上运行了这个测试,这个 $parent.find('.child'): 2357ms (和 .find('.child') )似乎是最好的,而 $('# parent').children('.child'): 8660ms 是最差的。
【解决方案3】:

方法一

使用 jQuery 不能更短更快。此调用直接调用$(context).find(selector)方法 2,由于优化),而后者又调用getElementById

方法二

做同样的事情,但没有一些不必要的内部函数调用。

方法3

使用children() 比使用find() 更快,但当然,children() 只会找到根元素的直接子元素,而find() 将自上而下递归搜索所有子元素(包括子子元素)

方法四

使用像这样的选择器,必须更慢。由于sizzle(它是来自 jQuery 的选择器引擎)工作从右到左,它会首先匹配所有类 .child,然后再查看它们是否是来自 id 'parent' 的直接子级。

方法五

正如您所说的正确,由于jQuery 函数中的一些优化,此调用还将创建一个$(context).find(selector) 调用,否则它也可能通过(较慢的)sizzle engine

【讨论】:

  • 你不是在谈论 var $parent = $("#parent") 是吗?当元素有一个类时,我看不到方法 1 如何使用 getElementById?
  • 我想同意,但是在方法 1 中,文档说,Internally, selector context is implemented with the .find() method - 请更新,我知道你对 OP 的标签感到困惑 :)
  • @Reigel:确实解决了这个问题。 @Marko:解析#parent代表一个id,如果是类,显然不会使用getElementById
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 2014-11-12
  • 1970-01-01
  • 1970-01-01
  • 2016-12-20
相关资源
最近更新 更多