Apa metode tercepat untuk memilih elemen turunan di jQuery?

101

Sejauh yang saya tahu, ada beberapa cara untuk memilih elemen anak di jQuery .

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

Metode 1 (dengan menggunakan ruang lingkup)

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

Metode 2 (metode find ())

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

Metode 3 (Hanya untuk anak-anak usia dini)

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

Metode 4 (melalui pemilih CSS) - disarankan oleh @spinon

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

Metode 5 (identik dengan Metode 2 ) - menurut @Kai

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

Saya tidak terbiasa dengan pembuatan profil untuk dapat menyelidiki ini sendiri, jadi saya ingin melihat apa yang Anda katakan.

PS Saya mengerti bahwa ini adalah kemungkinan duplikat dari pertanyaan ini, tetapi tidak mencakup semua metode.

Marko
sumber
Juga, @spinon - apakah itu hanya untuk anak-anak dekat? Spesifikasi CSS menyatakan "Cocok dengan semua elemen F yang merupakan turunan dari elemen E."
Marko
7
Anda tidak perlu khawatir mana yang lebih cepat (kecuali jika Anda melakukan manipulasi dom yang sangat besar) ... jQuery dibuat untuk menjadi sangat cepat ...
Reigel
Saya memiliki file HTML 2MB, jangan tanya bagaimana atau mengapa :)
Marko
1
Iya. Hanya keturunan tingkat pertama.
spinon
Ada satu cara lagi. $ ("# parent .child"). show (); yang identik dengan cara # 2. :)
Kai

Jawaban:

95

Metode 1 dan metode 2 identik dengan satu-satunya perbedaan adalah metode 1 perlu mengurai cakupan yang diteruskan dan menerjemahkannya menjadi panggilan ke $parent.find(".child").show();.

Metode 4 dan Metode 5 perlu mengurai selektor lalu memanggil: $('#parent').children().filter('.child')dan $('#parent').filter('.child')masing - masing.

Jadi metode 3 akan selalu menjadi yang tercepat karena metode ini perlu melakukan sedikit pekerjaan dan menggunakan metode paling langsung untuk mendapatkan anak tingkat pertama.

Berdasarkan uji kecepatan revisi Anurag di sini: http://jsfiddle.net/QLV9y/1/

Tes kecepatan: (Lebih banyak lebih baik)

Di Chrome , Metode 3 adalah yang terbaik lalu metode 1/2 dan kemudian 4/5

masukkan deskripsi gambar di sini

Di Firefox , Metode 3 masih yang terbaik daripada metode 1/2 dan kemudian 4/5

masukkan deskripsi gambar di sini

Di Opera , Metode 3 masih yang terbaik daripada metode 4/5 dan kemudian 1/2

masukkan deskripsi gambar di sini

Di IE 8 , meskipun secara keseluruhan lebih lambat daripada browser lain, ia masih mengikuti pengurutan Metode 3, 1,2,4,5.

masukkan deskripsi gambar di sini

Secara keseluruhan, metode 3 adalah metode umum terbaik untuk digunakan karena dipanggil secara langsung dan tidak perlu melintasi lebih dari satu tingkat elemen turunan tidak seperti metode 1/2 dan tidak perlu diurai seperti metode 4/5

Meskipun demikian, perlu diingat bahwa dalam beberapa metode ini kami membandingkan apel dengan jeruk karena Metode 5 melihat semua anak, bukan yang tingkat pertama.

Aaron Harun
sumber
Dengan identik, maksud Anda bahwa mereka berdua menggunakan logika yang sama untuk mencari?
Marko
4
Bukankah maksud Anda metode 1 dan 2 itu identik?
Guffa
Terima kasih @Aaron - tSaya ingin melihat apa yang orang lain pikirkan, saya akan menerima jawaban Anda jika semua orang setuju. Bersulang :)
Marko
@JP, maksud saya perlu sedikit waktu ekstra untuk mengenali bahwa ruang lingkup sedang diteruskan untuk menerjemahkannya ke dalam $parent.find(".child");perintah.
Aaron Harun
2
@Aaron @Marko - Tes mungkin sedikit miring karena kami selalu menggunakan node root sebagai konteks, dan dokumennya cukup besar. Meskipun demikian, saya melihat 1 dan 2 berbaris dalam 20 ops / detik satu sama lain di sebagian besar sesi. Dibandingkan dengan 1 dan 2, 4 adalah sekitar 100-200 ops lebih lambat, dan 5 adalah sekitar 400 ops lebih lambat yang dapat dimengerti karena ini melewati semua turunan dan bukan hanya anak-anak. Bagan - tinyurl.com/25p4dhq
Anurag
13

Metode 1

Tidak bisa lebih pendek dan lebih cepat menggunakan jQuery. Panggilan ini secara langsung turun ke $(context).find(selector)( metode 2 , karena pengoptimalan) yang pada gilirannya, memanggil getElementById.

Metode 2

Melakukan hal yang sama, tetapi tanpa beberapa panggilan fungsi internal yang tidak perlu.

Metode 3

menggunakan children()lebih cepat daripada menggunakan find(), tetapi tentu saja, children()hanya akan menemukan find()turunan langsung dari elemen root sedangkan akan mencari secara berulang dari atas ke bawah ke semua elemen anak (termasuk elemen sub anak)

Metode 4

Menggunakan selektor seperti ini, harus lebih lambat. Karena sizzle(yang merupakan mesin pemilih dari jQuery) bekerja dari kanan ke kiri , itu akan mencocokkan SEMUA kelas .childterlebih dahulu sebelum terlihat jika mereka adalah turunan langsung dari id 'induk'.

Metode 5

Seperti yang Anda nyatakan dengan benar, panggilan ini juga akan membuat $(context).find(selector)panggilan, karena beberapa pengoptimalan di dalam jQueryfungsi, jika tidak, bisa juga melalui (lebih lambat) sizzle engine.

jAndy
sumber
2
Anda tidak berbicara tentang var $ parent = $ ("# parent") kan? Saya tidak dapat melihat bagaimana Metode 1 dapat menggunakan getElementById ketika elemen tersebut memiliki kelas?
Marko
1
Saya ingin setuju tetapi, dalam metode 1, dokumen mengatakan, Internally, selector context is implemented with the .find() method-harap perbarui, saya tahu Anda bingung dengan label OP :)
Reigel
@ Reigel: benar memperbaikinya. @ Marko: parsing #parentmewakili sebuah id, jika itu adalah sebuah kelas, itu tidak akan digunakan dengan getElementByIdjelas.
jAndy
10

Karena ini adalah pos lama, dan banyak hal berubah seiring waktu. Sejauh ini saya telah melakukan beberapa pengujian pada versi browser terakhir, dan saya mempostingnya di sini untuk menghindari kesalahpahaman.

Menggunakan jQuery 2.1 pada browser yang kompatibel dengan HTML5 dan CSS3, kinerja berubah.

Berikut skenario dan hasil pengujiannya:

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>

Jadi, untuk 100.000 iterasi saya mendapatkan:

Statistik pemilih jQuery JS

(Saya telah menambahkannya sebagai img untuk tujuan pemformatan.)

Anda dapat menjalankan sendiri cuplikan kode untuk menguji;)

Vasil Popov
sumber
Oh! Kemudian sepertinya .find()melakukan pekerjaan dengan baik. Terus menggunakannya. :)
Andrew Surdu