Який найшвидший метод вибору нащадкових елементів у jQuery?


101

Наскільки я знаю, існує кілька способів вибору дочірніх елементів у jQuery .

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

Спосіб 1 (використовуючи область застосування)

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

Спосіб 2 (метод find ()

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

Спосіб 3 (лише для дітей, які мають безпосереднє значення)

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

Спосіб 4 (за допомогою селектора CSS) - запропоновано @spinon

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

Метод 5 (ідентичний методу 2 ) - згідно @Kai

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

Я не знайомий з профілюванням, щоб мати можливість це самостійно досліджувати, тому я хотів би побачити, що ти маєш сказати.

PS Я розумію, що це можливий дублікат цього питання, але він охоплює не всі методи.


Також @spinon - це лише для найближчих дітей? Специфікація CSS говорить: "Відповідає будь-якому елементу F, який є дочірнім елементом E."
Марко

7
Вам не потрібно хвилюватися, що з них швидше (якщо ви не робите дійсно маніпуляції з великим домом) ... jQuery був побудований для приголомшливого швидкого ...
Reigel

У мене HTML-файл розміром 2 Мб, не запитуйте, як і чому :)
Марко

1
Так. Лише нащадки першого рівня.
спінон

Є ще один спосіб. $ ("# батько. дитячий"). show (); що ідентично способу №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 дивиться на всіх дітей, а не на перших.


Під ідентичним ви маєте на увазі, що вони обидва використовують одну і ту ж логіку для пошуку?
Марко

4
Ви не маєте на увазі, що метод 1 і 2 є тотожними?
Guffa

Дякую @Aaron - я хотів би подивитися, що думають інші, я прийму вашу відповідь, якщо всі згодні. Ура :)
Марко

@JP, я маю на увазі, що потрібно визначити зайвий час, щоб визнати, що передається область для перекладу його в $parent.find(".child");команду.
Аарон Харун

2
@Aaron @Marko - Тести можуть бути трохи перекошені, оскільки ми завжди використовуємо кореневий вузол як контекст, і документ досить великий. Незважаючи на це, на більшості пробіжок я бачу 1 та 2 лінії в межах 20 ops / sec. Порівняно з 1 і 2, 4 на 100-200 ops повільніше, а 5 - на 400 ops повільніше, що зрозуміло, оскільки він проходить через усіх нащадків, а не лише дітей. Діаграма - tinyurl.com/25p4dhq
Анураг

13

Спосіб 1

Не можна бути коротшим та швидшим за допомогою jQuery. Цей виклик безпосередньо зводиться до $(context).find(selector)( метод 2 , завдяки оптимізації), який, у свою чергу, дзвонить getElementById.

Спосіб 2

Так само, але без зайвих внутрішніх функцій дзвінків.

Спосіб 3

використовуючи children() швидше, ніж використання find(), але, звичайно, children()знайдете лише прямі дитячі кореневі елементи, тоді як find()рекурсивно здійснюватиме пошук зверху вниз до всіх дочірніх елементів (включаючи допоміжні елементи)

Метод 4

Використання таких селекторів має бути повільніше. З тих пірsizzle (який є селекторним двигуном від jQuery) працює праворуч ліворуч , він .childспочатку буде відповідати ВСІМ класам, перш ніж з’явиться, чи є вони прямою дочіркою від id 'батьків'.

Метод 5

Як ви правильно сказали, цей виклик також створить $(context).find(selector)виклик через деяку оптимізацію в межах jQueryфункції, інакше він також може пройти через (повільніше) sizzle engine.


2
Ви не говорите про var $ parent = $ ("# батько")? Я не бачу, як метод 1 може використовувати getElementById, коли в елемента є клас?
Марко

1
Я хотів погодитись, але, у способі 1, документи говорять: - Internally, selector context is implemented with the .find() methodПолегшіть оновлення, я знаю, що ви заплуталися у етикетках ОП :)
Рейгель,

@Reigel: правда виправлено це. @Marko: розбір #parentявляє собою ідентифікатор, якщо це клас, 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()що це чудова робота. Продовжуючи його використовувати. :)
Ендрю Сурду,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.