Подтвердить что ты не робот

$.each() vs for() - и производительность

Это, в основном, только некоторые вещи, о которых мне было интересно, может быть, кто-то может дать мне немного больше информации о них, я поделюсь тем, что я заметил до сих пор!

Первое, что мне было интересно... есть ли какая-то разница или причина для использования:

$('element').each(function (i, el) { });

- против -

$.each($('element'), function (i, el) { });

Глядя на документы jQuery, я не вижу никаких рифм или причин для одного или другого (возможно, вы знаете экземпляр или дополнительные вещи, которые можно сделать друг с другом.

Но, что более важно, меня беспокоит скорость здесь

// As opposed to $.each() looping through a jQuery object
// -- 8x faster 
for (var i = 0, $('.whatever').length; i < len; i++) {
    $('.whatever')[i] // do stuff
}

Если вы посмотрите здесь jsFiddle DEMO здесь, вы увидите, что разница в скорости в основном эквивалентна любой из них, но что более важно, я чувствую, что всегда должен использовать циклы for()...

Я был всего лишь модульным тестированием (цикл через каждую из 5 различных функций сценария, 50 000 раз), просто перебирал кучу элементов списка и устанавливал data-newAttr, ничего особенного.


ВОПРОС: : Я думаю, мой самый большой вопрос: почему не всегда использовать для циклов, итерации через объект? Есть ли смысл использовать $.each()? Вы всегда используете for() петли даже при переходе через объекты jQuery?

jsFiddle DEMO здесь

Function type:                  Execution Time:
_testArea.each() + $(this)               1947   <-- using $(this) slows it down tremendously
$.each()         + $(this)               1940
_testArea.each() + el(plain JS)           458   <-- using the Element speeds things up
$.each()         + el(plain JS)           452
for() loop       + plainJS[0] iteration   236   <-- over 8x faster

Просто мои 2центы.:)

4b9b3361

Ответ 1

Одна вещь, которую .each() позволяет сделать, что не может быть выполнена с помощью цикла for цепочка.

$('.rows').each(function(i, el) {
    // do something with ALL the rows
}).filter('.even').each(function(i, el) {
    // do something with the even rows
});

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

Результат был не таким неожиданным, хотя я думаю, что накладные расходы end() были преувеличены здесь из-за комбинации нескольких элементов и многих циклов. Кроме этого: простые JS-контуры все еще немного быстрее, но зависит от того, имеет ли это значение повышенная читаемость .each() (и цепочка).

Ответ 2

Одна вещь, которую вы получаете с .each(), - это автоматическое локальное определение области видимости (потому что вы вызываете анонимную функцию для каждого объекта), что, в свою очередь, означает, что вы создаете еще больше анонимных функций/закрытий/обработчиков событий/независимо от каждого итерации, вам никогда не придется беспокоиться о том, что ваши обработчики используют переменную. То есть, JavaScript не действует, как другие языки, когда дело доходит до локальных областей, но поскольку вы можете объявить переменную где угодно, это может иногда обмануть вас.

Другими словами, это неверно:

var idx,el;
for (idx = 0; idx <someObjectArray.length; idx++){
   el = someObjectArray[idx]
   el.someEventHandler(function(){  
       alert( "this is element " + idx);
   }); 
}

Всякий раз, когда какой-либо из этих объектов вызывает свой "someEvent" после этого цикла (обратите внимание, что это сделано), предупреждение всегда будет сообщать, что было последним присвоено idx, которое должно быть (с момента времени вызывается) someObjectArray.length;

Чтобы сохранить правильный индекс, вы должны объявить локальную область, создать переменную и назначить эту переменную для использования.

var idx,el;
for (idx = 0; idx <someObjectArray.length; idx++){
   el = someObjectArray[idx];
   (function(){
       var localidx = idx;
       el.someEventHandler(function(){  
           alert( "this is element " + localidx);
       }); 
   })();
}

Как вы можете видеть, это так же уродливо, как черт, но оно должно работать. Каждый обработчик событий получает свою собственную копию localidx

Теперь сравните это с .each()

$(someObjectArray).each(function (idx, el) { 
   el.someEventHandler(function(){  
       alert( "this is element " + idx);
   }); 
});

Много проще, не так ли?

Ответ 3

jQuery.each vs for-loop

Преимущества jQuery.each:

  • Хорошо вписывается в код jQuery (цепочка и стиль).
  • Не стоит беспокоиться об объеме (ссылки на итератор и объект будут постоянными).
  • Может использоваться повсеместно (для всех видов объектов и итерации по клавишам объектов).

Преимущества для цикла:

  • Высокая производительность (для игр/анимаций/больших наборов данных).
  • Полный контроль над итератором (пропустить элементы, сращивание элементов из списка и т.д.).
  • For-loop всегда будет работать, потому что нет никакой зависимости от jQuery.
  • Такой же знакомый синтаксис, как и большинство других подобных языков.

Пример кода

Это пример кода того, как я предпочитаю перебирать список.

var list = ['a', 'b', 'c', 'd', 'e', 'f'];

jQuery.each:

$.each(list, function(i, v)
{
    // code...
});

Для цикла без замыкания:

for(var i=0,v,n=list.length;i<n;i+=1)
{
    v = list[i];
    // code...
}

За цикл с замыканием:

for(var i=0,n=list.length;i<n;i+=1)
{
    (function(i, v)
    {
        // code...
    })(i, list[i]);
}

Примечание. Я предлагаю вам использовать стандартный цикл for-loop и при необходимости использовать только закрытие. Однако, когда ваш код больше похож на jQuery, чем на Javascript, в любом случае было бы проще просто использовать $.each. В случае проблем с производительностью вы всегда можете изучить его впоследствии.

Ответ 4

Когда я пошел к вашей ссылке, вот два числа, которые я получил:

$.each() + el(plain JS) 401
for() loop + plainJS[0] iteration   377

Если разница в том, что она мала, то переходите к той, которая наиболее читаема, но если у вас очень высокие требования к времени, вам просто нужно пойти с тем, что в конечном итоге станет самым быстрым.

Я бы предложил вам написать свою программу, чтобы использовать три разных метода, два выше, а затем использовать foreach, найденный в новых версиях javascript, а для тех браузеров, которые его не поддерживают, вы можете добавить его в качестве прототипа.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach

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

Для вашего первого вопроса я бы пошел с $('element').each, так как его гораздо легче читать, но это только мое мнение.

Ответ 5

Раньше я выполнял несколько простых тестов производительности http://jsperf.com/forloops3. Кажется, что придерживаться простого, старое for loop (где это возможно) - это путь:)

Ответ 6

На самом деле существует большая разница между $.each() и $(). each().

Они делают несколько разные вещи в зависимости от того, что вы проходите.

http://api.jquery.com/each/ vs http://api.jquery.com/jquery.each/

jquery.each - это общий итератор, где $(). each() специфичен для коллекции jquery.

Также см.: http://jsperf.com/each-vs-each-vs-for-in/9