JQuery'de alt öğeleri seçmenin en hızlı yöntemi nedir?


101

Benim bildiğim gibi, alt öğeleri seçme birkaç yolu vardır jQuery .

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

Yöntem 1 (kapsam kullanarak)

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

Yöntem 2 (find () yöntemi)

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

Yöntem 3 (Yalnızca acil çocuklar için)

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

Yöntem 4 (CSS seçici aracılığıyla) - @spinon tarafından önerildi

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

Yöntem 5 ( Yöntem 2 ile aynı ) - @Kai'ye göre

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

Bunu kendi başıma araştırabilmek için profil oluşturmaya aşina değilim, bu yüzden ne söyleyeceğinizi görmek isterim.

Not: Bunun, bu sorunun olası bir kopyası olduğunu anlıyorum, ancak tüm yöntemleri kapsamıyor.


Ayrıca @spinon - bu sadece acil çocuklar için mi? CSS spesifikasyonu "E öğesinin alt öğesi olan herhangi bir F öğesiyle eşleşir" diyor.
Marko

7
Hangisinin daha hızlı olduğu konusunda gerçekten endişelenmenize gerek yok (gerçekten büyük bir dom manipülasyonu yapmıyorsanız) ... jQuery harika hızlı olacak şekilde tasarlandı ...
Reigel

2MB'lık bir HTML dosyam var, nasıl veya neden diye sormayın :)
Marko

1
Evet. Yalnızca birinci düzey torunlar.
spinon

Bir yol daha var. $ ("# ebeveyn. çocuk"). show (); 2 numaralı yolla aynıdır. :)
Kai

Yanıtlar:


95

Yöntem 1 ve yöntem 2 aynıdır ve tek fark, yöntem 1'in geçirilen kapsamı ayrıştırması ve bunu bir çağrıya çevirmesi gerektiğidir $parent.find(".child").show();.

Yöntem 4 ve Yöntem 5'in her ikisinin de seçiciyi ayrıştırması ve ardından sırasıyla : $('#parent').children().filter('.child')ve çağırması gerekir $('#parent').filter('.child').

Dolayısıyla, yöntem 3 her zaman en hızlısı olacaktır çünkü en az miktarda iş yapması gerekir ve birinci düzey çocukları elde etmek için en doğrudan yöntemi kullanır.

Anurag'ın burada revize edilmiş hız testlerine dayanmaktadır: http://jsfiddle.net/QLV9y/1/

Hız testi: (Daha Fazlası Daha İyidir)

On Chrome , Yöntem 3 en iyi o zaman yöntem 1/2 ve ardından 4/5 olduğunu

görüntü açıklamasını buraya girin

On Firefox , Yöntem 3 hala en iyi o zaman yöntem 1/2 ve ardından 4/5 olduğunu

görüntü açıklamasını buraya girin

On Opera , Yöntem 3 hala en iyi o zaman yöntem 4/5 ve ardından 1/2 olduğunu

görüntü açıklamasını buraya girin

On IE 8 genel diğer tarayıcılar daha, hala Yöntem 3, 1,2,4,5 sipariş takip yavaş olurken,.

görüntü açıklamasını buraya girin

Genel olarak, yöntem 3 , doğrudan çağrıldığı için genel olarak en iyi yöntemdir ve yöntem 1 / 2'den farklı olarak birden fazla alt öğe düzeyini geçmesi gerekmez ve yöntem 4/5 gibi ayrıştırılması gerekmez.

Yine de, bunların bazılarında elmaları portakallarla karşılaştırdığımızı, çünkü Yöntem 5'in birinci seviye çocuklar yerine tüm çocuklara baktığını unutmayın.


Aynı derken ikisinin de arama yapmak için aynı mantığı kullandıklarını mı söylüyorsunuz?
Marko

4
Yöntem 1 ve 2'nin aynı olduğunu söylemiyor musun?
Guffa

Teşekkürler @Aaron - Başkalarının ne düşündüğünü görmek istiyorum, eğer herkes kabul ederse cevabınızı kabul edeceğim. Şerefe :)
Marko

@JP, Demek istediğim, $parent.find(".child");komuta çevirmek için bir kapsamın geçildiğini anlamak için fazladan zaman alması gerekiyor .
Aaron Harun

2
@Aaron @Marko - Her zaman bağlam olarak kök düğümü kullandığımız ve belge oldukça büyük olduğu için testler biraz çarpık olabilir. Buna rağmen, çoğu çalışmada 1 ve 2'nin 20 işlem / saniye içinde birbirlerine sıralandığını görüyorum. 1 ve 2 ile karşılaştırıldığında, 4 yaklaşık 100-200 işlem daha yavaştır ve 5 yaklaşık 400 işlem daha yavaştır, bu anlaşılabilir bir durumdur çünkü sadece çocuklardan değil tüm torunlardan geçer. Grafik - tinyurl.com/25p4dhq
Anurag

13

Yöntem 1

JQuery kullanarak daha kısa ve daha hızlı olamaz. Bu çağrı doğrudan $(context).find(selector)( optimizasyon nedeniyle yöntem 2'ye ) iner ve bu da çağrı yapar getElementById.

Yöntem 2

Aynı şeyi yapıyor, ancak bazı gereksiz dahili işlev çağrıları olmadan.

Yöntem 3

kullanmak children(), kullanmaktan daha hızlıdır find(), ancak elbette, children()yalnızca kök öğenin doğrudan çocuklarını bulacak , ancak find()tüm alt öğeleri (alt öğeler dahil) yukarıdan aşağıya yinelemeli olarak arayacaktır.

Yöntem 4

Bunun gibi seçicileri kullanmak daha yavaş olmalı. Yana sizzleçalışır (jQuery gelen seçici motoru olan) sağ sola , TÜM sınıflar maç olacak .childonlar kimliği 'ebeveyn' doğrudan bir çocuk varsa görünüyor ilk önce.

Yöntem 5

Doğru bir şekilde belirttiğiniz gibi, bu çağrı $(context).find(selector), jQueryişlev içindeki bazı optimizasyonlardan dolayı bir çağrı da yaratacaktır , aksi takdirde (daha yavaş) da gidebilir sizzle engine.


2
Var $ parent = $ ("# parent") hakkında konuşmuyorsunuz, değil mi? Öğe bir sınıfa sahipken Yöntem 1'in getElementById'yi nasıl kullanabileceğini göremiyorum?
Marko

1
Kabul etmek istedim ama, yöntem 1'de, dokümanlar şöyle diyor: Internally, selector context is implemented with the .find() method-Lütfen güncelleyin, OP etiketlerinde
kafanızın

@Reigel: doğru düzeltildi. @Marko: ayrıştırma #parentbir kimliği temsil eder, eğer bir sınıfsa , getElementByIdaçıkça kullanmayacaktır .
jAndy

10

Eski bir gönderi olduğu ve zamanla işler değiştiği için. Şimdiye kadar son tarayıcı sürümlerinde bazı testler yaptım ve yanlış anlaşılmaları önlemek için buraya gönderiyorum.

HTML5 ve CSS3 uyumlu tarayıcılarda jQuery 2.1 kullanıldığında performans değişir.

İşte test senaryosu ve sonuçları:

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>

Yani, 100.000 yineleme için şunu elde ediyorum:

JS jQuery seçici istatistikleri

(Biçimlendirme amacıyla bunları img olarak ekledim.)

Kod parçacığını test etmek için kendiniz çalıştırabilirsiniz;)


Oh! O zaman .find()harika bir iş çıkarmış gibi görünüyor . Kullanmaya devam ediyorum. :)
Andrew Surdu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.