Производительность селектора jQuery с контекстом
Я читал эту статью Брэндона Аарона здесь, о том, как может помочь контекст jquery. Поэтому я подумал о том, чтобы сделать собственное испытание. Так вот что я сделал.
-
Создал DIV с id = "context" и вложенным DIV с id = "holder" в "#context", созданным ранее.
-
Создал вложенные DIV глубины 18 и добавил <div id="context"><div id="holder"></div></div>
к нему, в результате получив 20 вложенных DIV
-
Теперь я проверил время, затрачиваемое на доступ к "#holder" с помощью следующих селекторов:
а. $("#holder") // no context
б. $("#holder", "#context") // with "#context" selector string
с. $("#holder", $("#context")) // sending jquery object each time with selector "#context"
д. $("#holder", $context) // where, var $context = $("#context"). Caching jquery obj
Был отмечен каждый из случаев, когда доступ к X = 1000
раз и разность начала и окончания. Я нашел, что время для:
случай (а) был наименее последовательным 28-32 мсек [jquery-1.3.2]
случай (b) + (c) имел наивысшие времена 60-65 мсек и 70-75 мсек соответственно
случай (d) имел 40-50 мсек с 1 или 2 шипами.
Является ли эта базовая проверка действительной? Вы можете играть с JS-кодом здесь в JSBIN.
[Дайте мне знать, если я смогу улучшить этот тест каким-то образом]
Если ДА, то как этот "контекст" действительно помогает?
#NOTE: также замените jquery-1.3.2 на jquery-1.4.2 в режиме редактирования jsbin, и вы будете удивлены, увидев, что цифры растут: P
Ответы
Ответ 1
Контекст действительно помогает, когда у вас гораздо больше DOM, который вы просматриваете. Поиск идентификаторов уже очень быстрый, и контекст на самом деле не очень помогает в этом случае. Если контекст действительно может иметь значение, это когда вы выбираете имя тега или класс.
Попробуйте протестировать следующим образом: http://jsbin.com/aciji4/4
вы действительно можете увидеть, что время становится лучше для контекста, когда вы увеличиваете количество элементов в DOM следующим образом: http://jsbin.com/aciji4/6 p >
Ответ 2
Было бы разумно, что использование контекста займет больше времени (а не только с помощью селектора), поскольку в контексте используется метод .find(), поэтому, по сути, все, что вы действительно делаете, это
$('#context').find('#holder');
В основном я рассматриваю его как более простой способ идентифицировать элементы в событиях и итераторах, где изменяется контекст, потому что
$('.holder', this)
лучше, чем
$(this).find('.holder')
Ответ 3
Селектор # ID зависит от исходного документа document.getElementById. Это будет быстро, несмотря ни на что.
Попробуйте селектор, например div.class [атрибут = значение] с контекстом и без него. Например *, вы можете выбрать ссылку "Связанные" вопросы справа с помощью этого селектора:
// Selects anchor elements with href beginning with /questions/
$('a[href^=/questions/]')
Но, это быстрее, чтобы ограничить количество элементов привязки, которые должен обработать движок селектора, оценивая относительно дорогое соответствие текста:
$('a[href^=/questions/]', '.related')
* И игнорируя, очевидно, более простой класс .question-hyperlink для этих ссылок, для обсуждения.
Ответ 4
Для того, что стоит, $context = $("#context")
все еще использует объект jQuery, который затем должен быть преобразован в объект DOM.
Если вы используете $context = $("#context")[0]
, вы обнаружите, что он работает так же быстро, как и первый тест.
Ответ 5
Будьте осторожны, прежде чем собирать рефакторинг кода. Как и в #NOTE, jQuery с 1.4 работает совсем по-другому. Последняя версия может содержать еще больше оптимизаций.
Я изменил код jsbin выше, чтобы иметь недавний jQuery, и добавил некоторые дополнительные случаи. Вы увидите, теперь только те три (2,3,6) случая получили штраф за производительность, который создает еще один объект jQuery за раунд. Отдых работает в то же время.
Вы можете найти измененную версию здесь: http://jsbin.com/aciji4/63/
Ответ 6
Я взял код JSBin и поместил его в jsPerf Test
$context.find('. holder') в два раза быстрее как его ближайший конкурент, $('. holder', $context), и это хороший в десять раз быстрее, чем используется любой другой селектор.
В заключение, кешируйте свои селекторы и используйте .find() для максимальной производительности