Эффективность Javascript: "for" против "forEach" [закрыто]

105

Каков текущий стандарт в 2017 году в Javascript с циклами for () по сравнению с .forEach.

Сейчас я работаю свой путь через Кольт Стил «Web Dev Bootcamp» на Udemy и он выступает forEachнад forего учением. Тем не менее, я искал различные вещи во время упражнений в рамках курсовой работы и нахожу все больше и больше рекомендаций использовать for-loop, а не forEach. Большинство людей считают, что цикл for более эффективен.

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

Любой совет будет очень признателен.

тонироббинс
источник
11
Зачем привязывать себя к чьему-то субъективному представлению о стандарте 2017 года? Принять стандарт вневременного, как писать чистый, в сопровождении кода, зная , что инженеры работают над тем , чтобы наиболее часто используемыми конструкциями очень эффективно, а затем оптимизировать для выполнения , когда у вас есть проблемы с производительностью конкретной
2
Родного forсложно превзойти по чистой скорости. forEach()вызывает обратный вызов для каждой итерации; так что это, очевидно, влечет за собой некоторые накладные расходы.
canon
1
будучи разработчиком, которого я почти не использую for или foreach, большая часть работы выполняется с помощью методов map, filter или reduce.
AT
12
@AT при условии, что вы не один из тех парней, которые используют mapисключительно для итерации и отбрасывают новый массив, который он генерирует. Я не знаю, скольким людям мне пришлось исправить выбор этой конкретной функции только на этом сайте.
canon
1
@canon согласился, выбор цикла важен, и при выборе следует учитывать результат и остаток таких методов. Я считаю, что для удобочитаемости следует избегать использования простых циклов for.
AT

Ответы:

204

для

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

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

Это не означает, что for -loops всегда будет более эффективным, просто JS-движки и браузеры оптимизировали их для этого. На протяжении многих лет возникали компромиссы в отношении того, какая конструкция цикла более эффективна (для while, reduce, reverse-while и т. Д.) - разные браузеры и JS-движки имеют свои собственные реализации, которые предлагают разные методологии для получения тех же результатов. По мере дальнейшей оптимизации браузеров для удовлетворения требований к производительности, теоретически [].forEachможно было бы реализовать его таким образом, чтобы он был быстрее или сопоставим с for.

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

  • эффективный
  • раннее завершение цикла (почести breakи continue)
  • контроль состояния ( i<nможет быть любым, не привязанным к размеру массива)
  • переменная область видимости ( var iостается iдоступной после завершения цикла)

для каждого

.forEach- это методы, которые в основном перебирают массивы (также и другие перечисляемые объекты , такие как Mapи Setобъекты). Они новее и содержат код, который субъективно легче читать. Пример:

[].forEach((val, index)=>{
   ...
});

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

  • не требует настройки переменных (перебирает каждый элемент массива)
  • functions / arrow-functions охватывают переменную блоком.
    В приведенном выше примере valэто будет параметр вновь созданной функции. Таким образом, любые переменные, вызываемые valдо цикла, сохранят свои значения после его завершения.
  • субъективно более удобен в обслуживании, поскольку может быть легче определить, что делает код - он выполняет итерацию по перечислимому; тогда как цикл for может использоваться для любого количества схем цикла

Производительность

Производительность - непростая тема, которая обычно требует некоторого опыта, когда дело касается предусмотрительности или подхода. Чтобы заранее (при разработке) определить, какой объем оптимизации может потребоваться, программист должен иметь хорошее представление о прошлом опыте работы с проблемным случаем, а также хорошее понимание потенциальных решений.

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

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

Подходить

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

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

for (var i=0; i < arr.length; ++i ){}

Для каждой итерации цикла JavaScript arr.lengthизвлекает операции расчета стоимости поиска ключа в каждом цикле. Нет причин, по которым этого не должно быть:

for (var i=0, n=arr.length; i < n; ++i){}

Это делает то же самое, но извлекается только arr.lengthодин раз, кэшируя переменную и оптимизируя ваш код.

vol7ron
источник
25
Отличный, исчерпывающий, не самонадеянный ответ, не привязанный к конкретному моменту времени, реализации или тесту на микро-тестах.
1
Отлично, это именно то, что я искал, и дает намного больше глубины, чем могло бы видео. Я действительно ценю это, поскольку я новичок, так что нужно многому научиться, и это то, что легко пропустить, просто отдав предпочтение одному перед другим без причины, которая могла бы помешать вам в будущем. Большое спасибо!
tonyrobbins
3
for-loop часто имеет преимущество с точки зрения отладки: они просты, чтобы войти в них, установить точку останова и проверить. С forEach () дополнительный уровень обратного вызова может немного усложнить ситуацию.
Эрик Грейндж
1
@FelipeBuccioni, спасибо, я действительно собирался изучить это, поскольку я думаю, что теперь движки проверяют, будет ли изменен массив, чтобы определить, кэшируется ли длина. Хотя, для устаревших целей, я думаю, что механизмы оптимизации были не такими щедрыми, а длина снижала производительность на каждой итерации. Я посмотрю на вашу статью и включу это в ответ, когда у меня будет время, или, надеюсь, выдающийся член сообщества внесет поправку в качестве правки для меня :)
vol7ron
6
Мне очень нравится объяснение в этом ответе и фраза [...], if performance and optimization was everything, there would be no other code than machine or assembly.. Я считаю, что с letзаявлением для объявления локальной переменной области блока второе преимущество forEachбольше не является преимуществом перед forциклом, если только в среде без поддержки let.
user7393973