web-dev-qa-db-ja.com

jQueryで子孫要素を選択する最速の方法は何ですか?

私の知る限り、jQueryで子要素を選択する方法はいくつかあります。

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

方法1(スコープを使用して)

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

メソッド2(find()メソッド)

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

方法(直接の子供のみ)

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

方法4(CSSセレクター経由)-@spinonにより提案

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

方法5方法2と同じ)-@Kaiによる

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

私は自分でこれを調査できるプロファイリングに精通していないので、あなたが言っていることを見てみたいです。

追伸これは この質問 の重複の可能性があることを理解していますが、すべての方法を網羅しているわけではありません。

101
Marko

方法1方法2は同じですが、唯一の違いはmethod 1は、渡されたスコープを解析し、$parent.find(".child").show();への呼び出しに変換する必要があります。

方法4および方法5両方ともセレクターを解析してから、呼び出し:それぞれ$('#parent').children().filter('.child')および$('#parent').filter('.child')

したがって、method 3は、最小限の作業で最も直接的な方法を使用して第1レベルの子を取得するため、常に最速になります。

ここにあるAnuragの改訂された速度テストに基づいています: http://jsfiddle.net/QLV9y/1/

速度テスト:(多いほど良い)

Chromeでは、方法3が最適であり、次に方法1/2、次に4/5です

enter image description here

Firefoxで、方法3が最善で、方法1/2、4/5

enter image description here

Operaでは、方法3が最適であり、方法4/5、それから1/2

enter image description here

IE 8では、他のブラウザよりも全体的に低速ですが、方法3、1、2、4、5の順序に従います。

enter image description here

全体的に、method 3は、直接呼び出され、異なるように複数レベルの子要素をトラバースする必要がないため、使用するのに最も最適な方法です。メソッド1/2およびメソッド4/5のように解析する必要はありません

ただし、これらのいくつかでは、方法5が第1レベルの子ではなくすべての子を調べるため、リンゴとオレンジを比較していることに留意してください。

95
Aaron Harun

方法1

JQueryを使用して短くて速くすることはできません。この呼び出しは直接$(context).find(selector)方法2、最適化のため)になり、次にgetElementByIdを呼び出します。

方法2

同じことをしていますが、いくつかの不必要な内部関数呼び出しはありません。

方法

children()を使用するとfind()を使用するよりも高速ですが、もちろんchildren()はルート要素の直接の子のみを検出しますが、find()は検索しますすべての子要素(サブ子要素を含む)に対して再帰的にトップダウン

方法4

このようなセレクターの使用は、より遅くする必要があります。 sizzle(jQueryのセレクターエンジン)は右から左で動作するため、idからの直接の子であるかどうかを調べる前に、最初にすべてのクラス_.child_に一致します。 '親'。

方法5

正しく述べたように、この呼び出しはjQuery関数内の最適化により$(context).find(selector)呼び出しも作成します。そうでない場合は、(遅い)_sizzle engine_を経由することもあります。

13
jAndy

それは古い投稿であり、物事は時間とともに変化します。これまでの最新バージョンのブラウザーでいくつかのテストを行いましたが、誤解を避けるためにここに投稿しています。

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回の反復に対して:

JS jQuery selector stats

(フォーマットのためにそれらをimgとして追加しました。)

コードスニペットを自分で実行してテストできます;)

9
Vasil Popov