Qual è il metodo più veloce per selezionare gli elementi discendenti in jQuery?


101

Per quanto ne so, ci sono diversi modi per selezionare gli elementi figlio in jQuery .

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

Metodo 1 (utilizzando un ambito)

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

Metodo 2 (il metodo find ())

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

Metodo 3 (solo per bambini immediati)

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

Metodo 4 (tramite selettore CSS) - suggerito da @spinon

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

Metodo 5 (identico al metodo 2 ) - secondo @Kai

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

Non ho familiarità con la creazione di profili per essere in grado di indagare su questo da solo, quindi mi piacerebbe vedere cosa hai da dire.

PS Capisco che questo sia un possibile duplicato di questa domanda ma non copre tutti i metodi.


Inoltre, @spinon - è solo per bambini immediati? La specifica CSS dice "Corrisponde a qualsiasi elemento F figlio di un elemento E."
Marko

7
Non devi davvero preoccuparti di quale di questi sia più veloce (a meno che tu non stia facendo una grande manipolazione del dominio) ... jQuery è stato costruito per essere incredibilmente veloce ...
Reigel

Ho un file HTML da 2 MB, non chiedermi come o perché :)
Marko

1
Sì. Solo discendenti di primo livello.
spinone

C'è un altro modo. $ ("# genitore. figlio"). show (); che è identico al modo # 2. :)
Kai

Risposte:


95

Metodo 1 e il metodo 2 sono identici con l'unica differenza che il metodo 1 deve analizzare l'ambito passato e tradurlo in una chiamata a $parent.find(".child").show();.

Il metodo 4 e il metodo 5 devono entrambi analizzare il selettore e quindi chiamare semplicemente: $('#parent').children().filter('.child')e$('#parent').filter('.child') rispettivamente.

Quindi il metodo 3 sarà sempre il più veloce perché deve fare la minima quantità di lavoro e utilizza il metodo più diretto per ottenere bambini di primo livello.

Basato sui test di velocità rivisti di Anurag qui: http://jsfiddle.net/QLV9y/1/

Test di velocità: (più è meglio)

Su Chrome , il metodo 3 è il migliore, quindi il metodo 1/2 e quindi 4/5

inserisci qui la descrizione dell'immagine

Su Firefox , il metodo 3 è ancora il migliore quindi il metodo 1/2 e quindi 4/5

inserisci qui la descrizione dell'immagine

Su Opera , il metodo 3 è ancora il migliore quindi il metodo 4/5 e poi 1/2

inserisci qui la descrizione dell'immagine

Su IE 8 , sebbene complessivamente più lento di altri browser, segue comunque l'ordinamento del Metodo 3, 1,2,4,5.

inserisci qui la descrizione dell'immagine

Complessivamente, metodo 3 è il metodo migliore da usare in quanto viene chiamato direttamente e non ha bisogno di attraversare più di un livello di elementi figlio a differenza del metodo 1/2 e non ha bisogno di essere analizzato come il metodo 4/5

Tuttavia, tieni presente che in alcuni di questi stiamo confrontando le mele con le arance poiché il Metodo 5 considera tutti i bambini invece di quelli di primo livello.


Con identico intendi che entrambi usano la stessa logica per la ricerca?
Marko

4
Non vuoi dire che i metodi 1 e 2 sono identici?
Guffa

Grazie @Aaron - mi piacerebbe vedere cosa pensano gli altri, accetterò la tua risposta se tutti sono d'accordo. Saluti :)
Marko

@JP, voglio dire che è necessario dedicare un po 'di tempo in più per riconoscere che viene passato uno scope per tradurlo nel $parent.find(".child");comando.
Aaron Harun

2
@Aaron @Marko - I test potrebbero essere un po 'distorti poiché utilizziamo sempre il nodo radice come contesto e il documento è piuttosto grande. Nonostante ciò, vedo 1 e 2 allineare entro 20 operazioni / sec l'una dall'altra nella maggior parte delle corse. Rispetto a 1 e 2, 4 è circa 100-200 operazioni più lente e 5 è circa 400 operazioni più lente, il che è comprensibile perché attraversa tutti i discendenti e non solo i bambini. Grafico - tinyurl.com/25p4dhq
Anurag

13

Metodo 1

Non può essere più breve e più veloce usando jQuery. Questa chiamata arriva direttamente a $(context).find(selector)( metodo 2 , a causa dell'ottimizzazione) che a sua volta chiamagetElementById .

Metodo 2

Sta facendo lo stesso, ma senza alcune chiamate a funzioni interne non necessarie.

Metodo 3

usare children()è più veloce dell'uso find(), ma ovviamente children()troverà solo i figli diretti dell'elemento radice mentrefind() cercherà ricorsivamente dall'alto verso il basso in tutti gli elementi figlio (inclusi gli elementi figlio secondari)

Metodo 4

Usare selettori come questo deve essere più lento. Poiché sizzle(che è il motore di selezione di jQuery) funziona da destra a sinistra , corrisponderà a TUTTE le classi.child prima di vedere se sono un figlio diretto dall'id "genitore".

Metodo 5

Come hai affermato correttamente, questa chiamata creerà anche una $(context).find(selector)chiamata, a causa di una certa ottimizzazione all'interno della jQueryfunzione, altrimenti potrebbe anche passare attraverso il (più lento) sizzle engine.


2
Non stai parlando della var $ parent = $ ("# parent") vero? Non riesco a vedere come il metodo 1 potrebbe utilizzare getElementById quando l'elemento ha una classe?
Marko

1
Volevo essere d'accordo ma, nel metodo 1, la documentazione dice, Internally, selector context is implemented with the .find() method-per favore aggiorna, so che ti sei confuso sulle etichette dell'OP :)
Reigel

@ Reigel: vero risolto. @Marko: parsing#parent rappresenta un id, se è una classe, getElementByIdovviamente non verrà utilizzata .
jAndy

10

Dato che è un vecchio post e le cose cambiano con il tempo. Finora ho fatto alcuni test sulle ultime versioni del browser e lo sto pubblicando qui per evitare malintesi.

Utilizzando jQuery 2.1 su browser compatibili con HTML5 e CSS3 le prestazioni cambiano.

Ecco lo scenario e i risultati del test:

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>

Quindi, per 100000 iterazioni ottengo:

Statistiche selettore jQuery JS

(Li ho aggiunti come img per scopi di formattazione.)

Puoi eseguire tu stesso lo snippet di codice per testare;)


Oh! Quindi sembra che .find()faccia un ottimo lavoro. Continuando a usarlo. :)
Andrew Surdu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.