在jQuery中选择后代元素的最快方法是什么?

Mar*_*rko 101 performance jquery profiling jquery-selectors

据我所知,有很多方法可以在jQuery中选择子元素.

//Store parent in a variable  
var $parent = $("#parent");
Run Code Online (Sandbox Code Playgroud)

方法1 (使用范围)

$(".child", $parent).show();
Run Code Online (Sandbox Code Playgroud)

方法2 (find()方法)

$parent.find(".child").show();
Run Code Online (Sandbox Code Playgroud)

方法3 (仅限直系儿童)

$parent.children(".child").show();
Run Code Online (Sandbox Code Playgroud)

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

$("#parent > .child").show();
Run Code Online (Sandbox Code Playgroud)

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

$("#parent .child").show();
Run Code Online (Sandbox Code Playgroud)

我不熟悉分析能够自己调查这个,所以我很想知道你要说些什么.

PS我明白这可能是这个问题的重复,但并不涵盖所有方法.

Aar*_*run 95

方法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

替代文字http://tinyurl.com/2clyrbz

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

替代文字http://tinyurl.com/2e89tp5

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

替代文字http://tinyurl.com/2a9r9r8

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

替代文字http://tinyurl.com/2a8ag59

总的来说,方法3是使用的最佳方法,因为它被直接调用,并且它不需要遍历多个子元素级别,这与方法1/2不同,并且它不需要像方法4/5那样进行解析

但是,请记住,在其中一些中我们将苹果与橙子进行比较,因为方法5会查看所有孩子而不是第一级孩子.

  • 你不是说方法1和2是相同的吗? (4认同)
  • @Aaron @Marko - 由于我们总是使用根节点作为上下文,测试可能有点偏差,文档非常大.尽管如此,在大多数运行中我都看到1和2在20次操作/秒内相互排列.与1和2相比,4大约100-200 ops较慢,5大约400 ops较慢,这是可以理解的,因为它通过所有后代而不仅仅是孩子.图表 - http://tinyurl.com/25p4dhq (2认同)

jAn*_*ndy 13

方法1

使用jQuery不能更短更快.这个调用直接归结为$(context).find(selector)(方法2,由于优化),而这又是调用getElementById.

方法2

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

方法3

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

方法4

使用像这样的选择器必须更慢.因为sizzle(这是jQuery的选择器引擎)从右到左工作,所以它.child首先匹配所有类,然后才能看到它们是来自id"parent"的直接子节点.

方法5

正如你所说的那样,这个调用也会产生一个$(context).find(selector)调用,因为jQuery函数中有一些优化,否则它也可能会经历(较慢)sizzle engine.

  • 你不是在谈论var $ parent = $("#parent")你呢?当元素有一个类时,我看不出方法1如何使用getElementById? (2认同)

Vas*_*pov 9

因为它是一个老帖子,事情随着时间而变化.到目前为止,我对最后一个浏览器版本进行了一些测试,我在这里发布它是为了避免误解.

在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);
}
Run Code Online (Sandbox Code Playgroud)
<!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>
Run Code Online (Sandbox Code Playgroud)

所以,对于10万次迭代,我得到:

JS jQuery选择器统计信息

(我已将它们添加为img以用于格式化目的.)

你可以自己运行代码片段来测试;)