В jQuery более эффективно использовать filter() или просто делать это в each()?

В настоящее время у меня есть код, который извлекает данные через jQuery, а затем отображает его с помощью метода each.

Однако у меня возникла проблема с сортировкой, поэтому я изучил использование и добавил метод jQuery filter перед sort (что имеет смысл).

Теперь я смотрю на удаление sort, и мне интересно, должен ли я оставить вызов filter как есть, или переместить его обратно в each.

Примеры в документации jQuery API для фильтра содержат результаты моделирования, а не вывод текстового контента (в частности, не используя each()).

В документации в настоящее время указано, что "[t] он поставил селектор проверен на каждый элемент [...]", что заставляет меня полагать, что выполнение filter и each приведет к тому, что нефильтрованные элементы будут зацикливается в два раза, и только один раз, если проверка была сделана исключительно в цикле each.

Правильно ли я верю, что это более эффективно?

РЕДАКТИРОВАТЬ: пример манекена.

Итак, это:

// data is XML content
data = data.filter(function (a) {
    return ($(this).attr('display') == "true");
});
data.each(function () {
    // do stuff here to output to the page
});

В сравнении с этим:

// data is XML content
data.each(function () {
    if ($(this).attr('display') == "true") {
        // do stuff here to output to the page
    }
});

Ответ 1

Точно, как вы сказали:

В документации в настоящее время указывается что "поставляемый селектор проверено на каждый элемент [...]", что заставляет меня поверить, что фильтр, и каждый из них приведет к нефильтрованные элементы зацикливаются в два раза, и только один раз, если проверка производилась исключительно в каждом цикл.

Через ваш код мы можем ясно видеть, что вы используете each в обоих случаях, что уже является циклом. И filter сам по себе представляет собой еще один цикл (с if, если он для фильтрации). То есть мы сравниваем производительность между двумя циклами с одним циклом. Неизбежно меньше циклов = более высокая производительность.

Я создал эту скрипту и профилировал с помощью Fireglug Profiling Tool. Как и ожидалось, второй вариант только с одним циклом быстрее. Конечно, с этим небольшим количеством элементов разница составляла всего 0,062 мс. Но, очевидно, разница будет увеличиваться линейно с большим количеством элементов.

Поскольку многие люди очень обеспокоены тем, что разница небольшая, и вы должны выбирать в соответствии с ремонтопригодностью, я могу выразить свое мнение: я также согласен с этим. На самом деле, я думаю, что более удобный код без фильтра, но это только вопрос вкуса. Наконец, ваш вопрос был о том, что было более эффективным, и на это был дан ответ, хотя разница небольшая.

Ответ 2

Вы правы, что использование фильтра и каждый из них медленнее. Быстро использовать только каждый цикл. По возможности оптимизируйте его, чтобы использовать меньше циклов.

Но это микро-оптимизация. Это должно быть оптимизировано только тогда, когда оно "свободно" и не будет стоить читаемого кода. Я лично хотел бы использовать тот или иной вариант, основанный на предпочтении стиля/удобочитаемости, а не на производительности.

Если у вас нет огромных наборов элементов DOM, вы не заметите разницы (и если вы это сделаете, у вас возникнут большие проблемы).

И если вам небезразлична эта разница, вам не нужно использовать jQuery, потому что jQuery работает медленно.

Вам следует заботиться о читаемости и ремонтопригодности.

$(selector).filter(function() {
    // get elements I care about
}).each(function() {
    // deal with them
});

против

$(selector).each(function() {
    // get elements I care about
    if (condition) {
         // deal with them
    }
}

Какой бы ни был ваш код более читабельным и поддерживаемым, это оптимальный выбор. В качестве отдельного примечания фильтр намного более мощный, если используется с .map, а затем используется с .each.

Позвольте мне также отметить, что оптимизация от двух циклов до одного цикла оптимизируется от O(n) до O(n). Это не то, о чем вы должны заботиться. В прошлом я также чувствую, что "лучше" поставить все в один цикл, потому что вы только цикл один раз, но это действительно ограничивает вас использованием map/reduce/filter.

Запишите значащий, самодокументирующий код. Только оптимизировать узкие места.

Ответ 3

Я бы ожидал, что производительность здесь будет очень похожей, причем каждая из них будет немного быстрее (видимо, заметна в больших наборах данных, где фильтрованный набор по-прежнему велик). Фильтр, вероятно, просто петли по множеству в любом случае (кто-то поправьте меня, если я ошибаюсь). Итак, первый пример завершает полный набор, а затем петли меньшего набора. 2-й цикл просто один раз.

Однако, если это возможно, самым быстрым способом будет включение фильтра в ваш первоначальный селектор. Поэтому давайте скажем, что ваша текущая переменная данных является результатом вызова $("div"). Вместо того, чтобы называть это и затем фильтровать его, используйте его, чтобы начать с:

$("div[display='true']")

Ответ 4

Обычно я не беспокоюсь о микро-оптимизации, поскольку, поскольку в великой схеме вещей вам, скорее всего, будет гораздо больше беспокоиться о производительности, чем jQuery .each() vs. .filter(), но чтобы ответить на поставленный вопрос, вы должны получить наилучшие результаты, используя один .filter():

data.filter(function() {
  return ($(this).attr('display')==="true");
}).appendTo($('body'));

Для примитивного сравнения производительности между .each() и .filter() вы можете проверить этот код:

http://codepen.io/thdoan/pen/LWpwwa

Однако, если все, что вы пытаетесь сделать, это вывод всех узлов с display="true" на страницу, то вы можете просто сделать так, как предложил Джеймс Монтань (если node есть <element>):

$('element[display=true]').appendTo($('body'));