Phương pháp nhanh nhất để chọn các phần tử con trong jQuery là gì?


101

Theo như tôi biết, có một số cách để chọn các phần tử con trong jQuery .

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

Phương pháp 1 (bằng cách sử dụng một phạm vi)

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

Phương pháp 2 (phương thức find ())

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

Phương pháp 3 (Chỉ dành cho trẻ em ngay lập tức)

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

Phương pháp 4 (thông qua bộ chọn CSS) - được đề xuất bởi @spinon

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

Cách 5 (giống với Cách 2 ) - theo @Kai

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

Tôi không quen với việc lập hồ sơ để có thể tự mình điều tra vấn đề này, vì vậy tôi rất muốn biết bạn phải nói gì.

Tái bút Tôi hiểu rằng đây có thể là một bản sao của câu hỏi này nhưng nó không bao gồm tất cả các phương pháp.


Ngoài ra, @spinon - có phải chỉ dành cho trẻ em ngay lập tức không? Thông số CSS cho biết "Đối sánh bất kỳ phần tử F nào là phần tử con của phần tử E."
Marko

7
Bạn không thực sự phải lo lắng mà điều đó được nhanh hơn (trừ khi bạn đang thực hiện một thao tác dom thực sự lớn) ... jQuery được xây dựng để được awesome nhanh ...
Reigel

Tôi có một tệp HTML 2MB, đừng hỏi làm thế nào hoặc tại sao :)
Marko

1
Đúng. Chỉ con cháu cấp một.
spinon

Còn một cách nữa. $ ("# cha. con"). show (); giống với cách # 2. :)
Kai

Câu trả lời:


95

Phương pháp 1phương pháp 2 giống hệt nhau với điểm khác biệt duy nhất là phương pháp 1 cần phân tích cú pháp phạm vi được truyền và dịch nó thành lời gọi tới $parent.find(".child").show();.

Phương pháp 4Phương pháp 5 đều cần phân tích cú pháp bộ chọn và sau đó chỉ cần gọi: $('#parent').children().filter('.child')$('#parent').filter('.child')tương ứng.

Vì vậy, phương pháp 3 sẽ luôn là nhanh nhất vì cần ít công việc nhất và sử dụng phương pháp trực tiếp nhất để lấy trẻ đầu cấp.

Dựa trên các bài kiểm tra tốc độ đã được sửa đổi của Anurag tại đây: http://jsfiddle.net/QLV9y/1/

Kiểm tra tốc độ: (Nhiều hơn là Tốt hơn)

Trên Chrome , Phương pháp 3 là tốt nhất, sau đó là Phương pháp 1/2 và sau đó là 4/5

nhập mô tả hình ảnh ở đây

Trên Firefox , Phương pháp 3 vẫn là tốt nhất, sau đó là Phương pháp 1/2 và sau đó là 4/5

nhập mô tả hình ảnh ở đây

Trên Opera , phương pháp 3 vẫn là tốt nhất, sau đó là phương pháp 4/5 và sau đó là 1/2

nhập mô tả hình ảnh ở đây

Trên IE 8 , mặc dù tổng thể chậm hơn các trình duyệt khác, nhưng nó vẫn tuân theo thứ tự Phương pháp 3, 1,2,4,5.

nhập mô tả hình ảnh ở đây

Nhìn chung, phương pháp 3phương pháp tổng quát tốt nhất để sử dụng vì nó được gọi trực tiếp và nó không cần phải duyệt qua nhiều hơn một cấp của các phần tử con không giống như phương pháp 1/2 và nó không cần phải được phân tích cú pháp như phương pháp 4/5

Mặc dù vậy, hãy nhớ rằng trong một số trường hợp này, chúng ta đang so sánh quả táo với quả cam vì Phương pháp 5 xem xét tất cả trẻ em thay vì những đứa trẻ cấp một.


Bạn có nghĩa là cả hai đều sử dụng cùng một logic để tìm kiếm?
Marko

4
Ý bạn không phải là phương pháp 1 và 2 giống hệt nhau?
Guffa

Cảm ơn @Aaron - tôi muốn xem những người khác nghĩ gì, tôi sẽ chấp nhận câu trả lời của bạn nếu mọi người đồng ý. Chúc mừng :)
Marko

@JP, ý tôi là cần thêm một chút thời gian để nhận ra rằng một phạm vi đang được chuyển để dịch nó thành $parent.find(".child");lệnh.
Aaron Harun

2
@Aaron @Marko - Các thử nghiệm có thể hơi lệch một chút vì chúng tôi luôn sử dụng nút gốc làm ngữ cảnh và tài liệu khá lớn. Mặc dù vậy, tôi thấy 1 và 2 xếp hàng với nhau trong vòng 20 ops / giây trong hầu hết các lần chạy. So với 1 và 2, 4 chậm hơn khoảng 100-200 ops và 5 chậm hơn khoảng 400 ops, điều này có thể hiểu được vì nó đi qua tất cả các con cháu chứ không chỉ trẻ em. Chart - tinyurl.com/25p4dhq
Anurag

13

Phương pháp 1

Không thể ngắn hơn và nhanh hơn bằng cách sử dụng jQuery. Cuộc gọi này trực tiếp đi xuống $(context).find(selector)( phương pháp 2 , do tối ưu hóa), đến lượt nó, sẽ gọi getElementById.

Phương pháp 2

Làm tương tự, nhưng không có một số lệnh gọi hàm nội bộ không cần thiết.

Phương pháp 3

sử dụng children()nhanh hơn sử dụng find(), nhưng tất nhiên, children()sẽ chỉ tìm thấy các phần tử con trực tiếp của phần tử gốc trong khi find()sẽ tìm kiếm đệ quy từ trên xuống cho tất cả các phần tử con (bao gồm cả các phần tử con)

Phương pháp 4

Sử dụng các bộ chọn như thế này, phải chậm hơn. Vì sizzle(là công cụ bộ chọn từ jQuery) hoạt động từ phải sang trái , nó sẽ khớp với TẤT CẢ các lớp .childtrước khi xem chúng có phải là con trực tiếp từ id 'cha' hay không.

Phương pháp 5

Như bạn đã nói chính xác, cuộc gọi này cũng sẽ tạo ra một $(context).find(selector)cuộc gọi, do một số tối ưu hóa trong jQueryhàm, nếu không, nó cũng có thể đi qua (chậm hơn) sizzle engine.


2
Bạn không nói về var $ parent = $ ("# parent") phải không? Tôi không thể hiểu cách Phương pháp 1 có thể sử dụng getElementById khi phần tử có một lớp?
Marko

1
Tôi muốn đồng ý nhưng, trong phương pháp 1, tài liệu nói, Internally, selector context is implemented with the .find() methodcập nhật -Xin, tôi biết bạn đã nhầm lẫn trên nhãn của OP :)
Reigel

@Reigel: true đã sửa điều đó. @Marko: phân tích cú pháp #parentđại diện cho một id, nếu nó là một lớp, nó sẽ không sử dụng getElementByIdrõ ràng.
jAndy

10

Vì nó là một bài cũ, và mọi thứ thay đổi theo thời gian. Tôi đã thực hiện một số thử nghiệm trên các phiên bản trình duyệt cuối cùng cho đến nay và tôi đăng nó ở đây để tránh hiểu lầm.

Sử dụng jQuery 2.1 trên các trình duyệt tương thích HTML5 và CSS3, hiệu suất sẽ thay đổi.

Đây là kịch bản thử nghiệm và kết quả:

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>

Vì vậy, với 100 000 lần lặp tôi nhận được:

Số liệu thống kê về bộ chọn JS jQuery

(Tôi đã thêm chúng dưới dạng img cho mục đích định dạng.)

Bạn có thể tự chạy đoạn mã để kiểm tra;)


Oh! Sau đó, có vẻ như .find()làm một công việc tuyệt vời. Tiếp tục sử dụng nó. :)
Andrew Surdu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.