array.forEach работает быстрее, чем собственная итерация? Как? - PullRequest
8 голосов
/ 02 апреля 2012

http://jsperf.com/testing-foreach-vs-for-loop

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

Что здесь происходит?За кулисами оптимизация?Или .forEach чище И быстрее?

Тестирование в Chrome 18.0.1025.142 32-разрядная на Windows Server 2008 R2 / 7 64-разрядная

Ответы [ 5 ]

9 голосов
/ 02 апреля 2012

Есть много итерационных оптимизаций, которых нет в вашем цикле for, таких как:

  • кеширует длину массива
  • итерация назад
  • использовать счетчик ++ вместо счетчика ++

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

См. этот jsperf для некоторых примеров.

Edit: ссылки для postfix vs prefix perf test и с повторением в обратном направлении . Мне не удалось найти ссылку для использования + = 1 вместо ++, поэтому я удалил ее из списка.

4 голосов
/ 02 апреля 2012

ОБНОВЛЕНИЕ:

Многие старые уловки в этих ответах отлично подходят для интерпретируемого JS в старых браузерах.

В любой современной реализации JS, включая все современные браузеры, Node и последниеМобильные веб-просмотры, встроенные функции могут фактически кэшироваться JIT (JS-компилятором), что делает forEach гораздо более быстрой опцией для итерации массива, как правило.Раньше было наоборот, когда простое обращение к функции неоднократно требовало процесса наращивания / разрыва, который мог бы серьезно снизить производительность нетривиального цикла.

Для лучшей производительности я бы избегал ссылаться на все, чтоне был передан в качестве аргумента или определен внутри самой функции, если не требуется.Я не уверен на 100%, что это имеет значение, но я мог понять, почему это так.

Значения получателя, которые включают в себя любой тип процесса поиска, например, длины массива или свойства узла DOM, вероятно, все еще лучше кэшируются в переменную.

Но помимо этого я бы постарался просто позволить основному принципу избегания работы направлять ваши усилия.Хорошие примеры этого - предварительный расчет вещей, которые не нужно пересчитывать в цикле, или кэширование результата селектора запросов в var, а не копаться в DOM.Слишком сильная попытка воспользоваться преимуществами поведения JIT, вероятно, станет довольно загадочной и вряд ли сохранится со временем или во всех JIT.

СТАРЫЙ ОТВЕТ:

Хорошо, забудьте стену текста,Пункты маркированного списка:

var i = someArray.length; //length is cached
someArray.reverse(); //include this only if iterating in 0-(length-1) order is important

while(i--){
//run a test statement on someArray[i];
}
  • длина кэшируется и немедленно включается в индекс

  • Преимущество повторения в обратном направлении в JS AFAIK позволяет избежатьлогический оператор с двумя операндами.В этом случае мы просто оцениваем число.Это правда или ноль и ложь.

  • Я также нахожу это элегантным.

1 голос
/ 02 апреля 2012

Чтение length из array на каждой итерации может быть медленным, но forEach обычно медленнее, потому что вызов функции не является дешевой операцией в js.

PS: forEach на 14% медленнее на FF10.

0 голосов
/ 02 апреля 2012

Возможно, for () медленнее, потому что цикл применяет 'array.length' к каждой итерации, чтобы получить длину массива.

Попытка:

var nri = array.length;
for( var i = 0; i < nri; i++ ){
   // ...
}
0 голосов
/ 02 апреля 2012

Они примерно одинаковы для меня в Опере.Следует отметить, что условное выражение в for () - это array.length.Если вы кешируете длину массива в переменной, а затем зацикливаетесь, вы должны увидеть лучшую производительность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...