Лучший способ оптимизировать селектор jQuery и почему?
Я использую этот селектор jQuery несколько раз в моем JSP:
$("#customers tbody tr td input[type='checkbox'][name='selectedCustomers']")
Решение, которое я нашел в некоторых блогах, это то, что я должен сделать в первую очередь:
var customer=$('#customers')
И затем используйте вышеуказанный объект клиента для дальнейших вызовов.
customer.find("tbody tr td input[type='checkbox'][name='selectedCustomers']")
Мой вопрос в том, поможет ли это решение и почему?
Мое понимание
Когда я делаю
$("#customers tbody tr td input[type='checkbox'][name='selectedCustomers']")
jQuery внутренне сначала получит объект, связанный с div id="customers"
(by document.getElementById( "клиенты" )), а затем перейдет к указанному
checkbox
. И если я пойду по предлагаемому решению, то document.getElementById("customers")
будет запущен только один раз, а остальные будут одинаковыми. Поэтому я спасаю себя от ненужного множественного document.getElementById
, но остальное будет таким же. Правильно ли я понимаю? Если да, то, насколько мне известно, document.getElementById
более дорогостоящая операция?
EDIT: -
Я не использую только выше указанного селектора несколько раз, но также и другой возможный селектор под div id = "клиент". Поэтому вопрос снова заключается в том, что разница в производительности, если я сначала кэширую объект клиента, и если я этого не делаю?
Ответы
Ответ 1
Вам не нужно быть таким специфическим. Я предполагаю, самое большее, это:
$('#customers td [name="selectedCustomers"]')
..., что должно повысить производительность. Затем, если вы каждый раз запрашиваете selectedCustomers
, вы должны кэшировать все это:
var selectedCustomers = $('#customers td [name="selectedCustomers"]');
В противном случае, если имя динамическое, и у вас есть только один элемент с тем же именем на странице...
var item = $(document.getElementsByName(someName)[0]);
Кэширование только $('#customers')
, с другой стороны, довольно бессмысленно. .find
on customers
будет работать так же, как и весь селектор, в первую очередь, с поддержкой querySelector
.
Ответ 2
Кажется, вам не хватает основной точки кеширования объекта. После того, как объект будет кэширован, любой дальнейший обход или манипуляция внутри этого селектора будет выполняться на сохраненном объекте и не требует поиска DOM, чтобы сначала найти селектор и создать коллекцию каждый раз, когда вам нужно его использовать.
Каждый раз, когда вы вызываете $("#customers tbody tr td input[type='checkbox'][name='selectedCustomers']")
, поиск документа должен выполняться для создания коллекции элементов, прежде чем любые изменения могут быть внесены в коллекцию.
Кэширование средства сбора данных не требует дальнейших поисков, поэтому улучшается производительность
/* locate and store the collection once*/
var $checkboxes=$("#customers tbody input[name='selectedCustomers']");
/* look within previously stored collection*/
$checkboxes.filter(/* expression*/ ).doSomething();
Использование document.getElementById
будет быстрее, чем поиск в jQuery, просто потому, что он не требует дополнительных вызовов функций, созданных библиотекой jQuery. Однако, если вы хотите использовать результат как объект jQuery, например:
$( document.getElementById('foo'))
выигрыши, вероятно, не стоит беспокоиться об одном использовании для кэширования объекта
Ответ 3
Итак, я избавляюсь от ненужного множественного document.getElementById
, но остальное будет таким же.
Да. Но, возможно, также нет, поскольку селектора оцениваются справа налево (см. эта статья или this SO вопрос). И если предположить, что это эффективный движок, ему было меньше работы, если он делает эту оценку только в части дерева документов, если вы сначала выберите #customers
, а затем .find()
. Но я не уверен в этом на 100%.
Является ли document.getElementById
более дорогостоящей операцией?
Нет, это очень дешево. Идентификаторы являются стандартным атрибутом для идентификации отдельных элементов, и браузеры будут создавать для него очень эффективные таблицы поиска - вы можете считать, что это почти O(1)
.
customer.find("tbody tr td input[type='checkbox'][name='selectedCustomers']")
С другой стороны, запросы выбора DOM, которые должны оценивать дерево DOM, очень дорогостоящи, особенно если они выполняются вручную в JS-коде (jQuery sizzle) и не являются родными - хотя этот довольно простой запрос будет делегирован на native querySelectorAll
.
Я предполагаю, что #customers
- ваш элемент таблицы. Поэтому для производительности пропустите теги tbody tr td
, они обязательны (если вы не использовали их для явного исключения флажков из элементов <thead>
/<tfoot>
или <th>
). В любом случае вы не найдете <input>
в качестве прямого дочернего элемента таблицы, а механизм выбора гораздо меньше.
Кроме того, если вы хорошо знаете свою разметку и можете сделать предположение, что только флажки имеют этот атрибут name
, вы можете также опустить селектор атрибутов типов тэгов и типов. И это означает, что вы можете делегировать нативный getElementsByName
, который должен немного повысить производительность:
$(document.getElementById("customers").getElementsByName("selectedCustomers"))
Если вам нужно проверить, что элементы являются флажками, вы все равно можете их фильтровать. При этом вы можете получить
$(customer.get(0).getElementsByName("selectedCustomers")).filter(":checkbox")
Однако для доказательства повышения производительности вы можете тестировать, тестировать, тестировать; и вам нужно будет сделать это на своей полной странице.
Ответ 4
http://jsperf.com/different-jquery-selector-tests
Проверьте этот маленький тест. В основном $('# div'). Find ('# p'); - самый быстрый и $('div'). Find ('# p'); является самым медленным.