วิธีที่เร็วที่สุดในการเลือกองค์ประกอบลูกหลานใน jQuery คืออะไร?


101

เท่าคือผมรู้ว่ามีหลายวิธีในการเลือกองค์ประกอบของเด็กในjQuery

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

วิธีที่ 1 (โดยใช้ขอบเขต)

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

วิธีที่ 2 (วิธีค้นหา ())

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

วิธีที่ 3 (สำหรับเด็กในระยะใกล้เท่านั้น)

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

วิธีที่ 4 (ผ่านตัวเลือก CSS) - แนะนำโดย @spinon

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

วิธีที่ 5 (เหมือนกับวิธีที่ 2 ) - ตาม @Kai

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

ฉันไม่คุ้นเคยกับการทำโปรไฟล์เพื่อให้สามารถตรวจสอบสิ่งนี้ได้ด้วยตัวเองดังนั้นฉันอยากจะเห็นสิ่งที่คุณพูด

ปล. ฉันเข้าใจว่านี่อาจเป็นคำถามที่ซ้ำกันได้แต่ไม่ครอบคลุมทุกวิธี


นอกจากนี้ @spinon - มีไว้สำหรับเด็ก ๆ เท่านั้นหรือไม่? ข้อกำหนด CSS ระบุว่า "จับคู่องค์ประกอบ F ใด ๆ ที่เป็นลูกขององค์ประกอบ E"
Marko

7
คุณไม่ต้องกังวลว่าอันไหนเร็วกว่า (เว้นแต่ว่าคุณจะทำการจัดการโดมใหญ่จริงๆ) ... jQuery ถูกสร้างขึ้นมาเพื่อให้เร็วที่สุดยอดเยี่ยม ...
Reigel

ฉันมีไฟล์ HTML ขนาด 2MB อย่าถามว่าทำไมหรืออย่างไร :)
Marko

1
ใช่. ผู้สืบทอดระดับแรกเท่านั้น
spinon

มีอีกหนึ่งวิธี $ ("# parent .child") แสดง (); ซึ่งเหมือนกับวิธี # 2 :)
ไก่

คำตอบ:


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

ใส่คำอธิบายภาพที่นี่

ในFirefoxวิธีที่ 3 ยังคงดีที่สุดแล้ววิธีที่ 1/2 และ 4/5

ใส่คำอธิบายภาพที่นี่

ในOperaวิธีที่ 3 ยังคงดีที่สุดแล้ววิธีที่ 4/5 และ 1/2

ใส่คำอธิบายภาพที่นี่

บนIE 8ในขณะที่โดยรวมช้ากว่าเบราว์เซอร์อื่น ๆ แต่ก็ยังคงเป็นไปตามวิธีที่ 3, 1,2,4,5 เรียงลำดับ

ใส่คำอธิบายภาพที่นี่

โดยรวมแล้ววิธีที่ 3เป็นวิธีที่ดีที่สุดในการใช้เนื่องจากเรียกโดยตรงและไม่จำเป็นต้องสำรวจองค์ประกอบลูกมากกว่าหนึ่งระดับซึ่งแตกต่างจากวิธี 1/2 และไม่จำเป็นต้องแยกวิเคราะห์เหมือนวิธี 4/5

อย่างไรก็ตามโปรดจำไว้ว่าในบางกรณีเรากำลังเปรียบเทียบแอปเปิ้ลกับส้มเนื่องจากวิธีที่ 5 มองไปที่เด็กทุกคนแทนที่จะเป็นระดับแรก


เหมือนกันคุณหมายความว่าทั้งสองใช้ตรรกะเดียวกันในการค้นหา?
Marko

4
คุณไม่ได้หมายความว่าวิธีที่ 1 และ 2 เหมือนกันหรือ?
Guffa

ขอบคุณ @Aaron - ฉันต้องการเห็นว่าคนอื่นคิดอย่างไรฉันจะยอมรับคำตอบของคุณหากทุกคนเห็นด้วย ไชโย :)
Marko

@JP ฉันหมายความว่าต้องใช้เวลาเพิ่มอีกนิดในการรับรู้ว่ามีการส่งขอบเขตเพื่อแปลเป็น$parent.find(".child");คำสั่ง
Aaron Harun

2
@Aaron @Marko - การทดสอบอาจเบ้เล็กน้อยเนื่องจากเราใช้รูทโหนดเป็นบริบทเสมอและเอกสารค่อนข้างใหญ่ อย่างไรก็ตามฉันเห็น 1 และ 2 ต่อกันภายใน 20 ครั้ง / วินาทีในการวิ่งส่วนใหญ่ เมื่อเทียบกับ 1 และ 2 แล้ว 4 จะช้ากว่าประมาณ 100-200 ops และ 5 จะช้ากว่าประมาณ 400 ops ซึ่งเป็นที่เข้าใจได้เพราะมันผ่านลูกหลานทั้งหมดไม่ใช่แค่เด็ก แผนภูมิ - tinyurl.com/25p4dhq
Anurag

13

วิธีที่ 1

ไม่สามารถสั้นลงและเร็วขึ้นโดยใช้ jQuery สายนี้โดยตรงได้รับลงไป$(context).find(selector)( วิธีที่ 2เนื่องจาก optimazation) getElementByIdซึ่งในการเปิดสาย

วิธีที่ 2

กำลังทำเช่นเดียวกัน แต่ไม่มีการเรียกใช้ฟังก์ชันภายในที่ไม่จำเป็น

วิธีที่ 3

การใช้children()นั้นเร็วกว่าการใช้find()แต่แน่นอนว่าchildren()จะพบเฉพาะลูกโดยตรงขององค์ประกอบรูทในขณะที่find()จะค้นหาจากบนลงล่างซ้ำ ๆ ไปยังองค์ประกอบลูกทั้งหมด (รวมถึงองค์ประกอบลูกย่อย)

วิธีที่ 4

การใช้ตัวเลือกเช่นนี้จะต้องช้าลง เนื่องจากsizzle(ซึ่งเป็นเครื่องมือเลือกจาก jQuery) ทำงานจากขวาไปซ้ายมันจะจับคู่คลาสทั้งหมด.childก่อนที่จะดูว่าเป็นลูกโดยตรงจาก id 'parent' หรือไม่

วิธีที่ 5

ในขณะที่คุณระบุไว้อย่างถูกต้องสายนี้ยังจะสร้าง$(context).find(selector)โทรเนื่องจาก optimazation บางภายในjQueryฟังก์ชั่นอย่างอื่นก็ยังสามารถผ่านไป sizzle engine(ช้ากว่า)


2
คุณไม่ได้พูดถึง var $ parent = $ ("# parent") ใช่ไหม ฉันไม่เห็นว่าวิธีที่ 1 สามารถใช้ getElementById ได้อย่างไรเมื่อองค์ประกอบมีคลาส?
Marko

1
ฉันต้องการที่จะเห็นด้วย แต่ในวิธีที่ 1 เอกสารบอกว่าInternally, selector context is implemented with the .find() method- โปรดอัปเดตฉันรู้ว่าคุณสับสนกับป้ายกำกับของ OP :)
Reigel

@ Reigel: จริงคงที่ @Marko: การแยกวิเคราะห์#parentหมายถึง id หากเป็นคลาสจะไม่ใช้getElementByIdอย่างชัดเจน
jAndy

10

เนื่องจากเป็นโพสต์เก่าและสิ่งต่างๆก็เปลี่ยนไปตามกาลเวลา ฉันได้ทำการทดสอบเบราว์เซอร์เวอร์ชันล่าสุดแล้วและฉันโพสต์ไว้ที่นี่เพื่อหลีกเลี่ยงความเข้าใจผิด

การใช้ jQuery 2.1 บนเบราว์เซอร์ที่เข้ากันได้กับ HTML5 และ CSS3 ประสิทธิภาพจะเปลี่ยนไป

นี่คือสถานการณ์การทดสอบและผลลัพธ์:

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

(ฉันได้เพิ่มเป็น img เพื่อวัตถุประสงค์ในการจัดรูปแบบ)

คุณสามารถเรียกใช้ข้อมูลโค้ดด้วยตัวคุณเองเพื่อทดสอบ;)


โอ้! ดูเหมือนว่า.find()จะทำงานได้ดี ใช้มันอย่างต่อเนื่อง :)
Andrew Surdu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.