Производительность селектора jQuery - PullRequest
5 голосов
/ 11 сентября 2009

У меня огромные различия в производительности в зависимости от того, как я выражаю свои селекторы. Например, посмотрите на эти 2 селектора, которые выбирают одинаковые элементы:

A) someTableRow.find("td.someColumnClass").find("span.editMode").find("input")
B) someTableRow.find("td.someColumnClass span.editMode input")

Я ожидал бы, что B) будет быстрее, поскольку есть только 1 вызов, но на самом деле я обнаружил, что A) выполняется примерно в 8 раз быстрее. Я понятия не имею, почему, у кого-нибудь есть понимание? Спасибо

Ответы [ 6 ]

14 голосов
/ 11 сентября 2009

Предполагая, что вы используете по крайней мере jQuery 1.3 (т.е. с добавлением Sizzle), производительность, которую вы видите, связана с изменением, в котором используется DOM. С здесь :

До jQuery 1.2.6 включительно Селектор двигателя работал в режиме «сверху вниз» (или «слева направо»). JQuery 1.3.x (то есть Sizzle , в который встраивается jQuery) введено «снизу вверх» (или "справа налево") подход к запросам ДОМ.

Во втором примере ("td.someColumnClass span.editMode input") Sizzle эффективно делает это:

  1. получить все input элементов внутри someTableRow
  2. для каждого найденного элемента input, пройдите его дерево предков для span элементов с помощью class="editMode". Удалите input элементы, у которых нет этих предков
  3. для каждого span.editMode найденного элемента, пройдите его дерево предков для td элементов с class="someColumnClass". Удалите input элементов, у которых нет этих предков

В вашем первом примере, однако, вы квалифицируете каждый шаг явным образом при каждом вызове find(), определяя контекст и проходя вниз оттуда. Вы применяете подход «сверху вниз». Это эквивалентно передаче в контексте на каждом шаге, который обычно считается повышением производительности :

$('input', $('span.editMode', $('td.someColumnClass', someTableRow)))
2 голосов
/ 11 сентября 2009

Поскольку вы сокращаете контекст для поиска.

В случае B необходимо выполнить поиск по каждому элементу DOM, чтобы проверить, соответствует ли он критериям.

В случае A is может быстро решить игнорировать все, что не является "td.someColumnClass", тогда он может взять это подмножество DOM и игнорировать все, что не находится в "span.editMode". Таким образом, он имеет гораздо меньший набор элементов для поиска, чтобы найти «входные данные».

1 голос
/ 01 декабря 2009

Я провел небольшое исследование производительности jQuery Selector. Большая проблема - поиск по имени класса в Internet Explorer. IE не поддерживает getElementsByClassName - поэтому jQuery и другие фреймворки «переопределяют» его в JavaScript, перебирая все элементы DOM. Просмотрите следующий аналитический блог о jQuery Selector Performance

1 голос
/ 11 сентября 2009

Мой опыт работы с JQuery немного отличается от CSS.

Сокращение контекста до поиска - это ключ, как указал Джош.

Я считаю использование двух селекторов параметров действительно быстрым

Как это сравнить скорость?

Тебе не нужны все переменные, это просто чтобы понять, что я делаю.

var columnClasses = $('.someColumnClass');
var tableCell = $('td', columnclasses);
var editMode = $('.editmode', tableCell);
var spanInside = $('span', editMode);
var inputFinally = $('input', spanInside);

Доброжелательность,

Dan

1 голос
/ 11 сентября 2009

А больше звонков, но проще. Б один звонок, но более сложный. В этом случае сложность вызова значительно превышает количество вызовов.

0 голосов
/ 11 сентября 2009

Здесь действительно интересная статья о производительности селектора: http://blogs.atlassian.com/developer/2009/08/jquery_bondage.html

В ней автор показывает расширение jQuery «связывание», которое показывает, сколько раз функция оценивается.

...