Итак, циклы — фундаментальная часть программирования, потому что они позволяют нам запускать «блок» последовательного кода n раз. Это позволяет нам делать самые разные вещи, от группировки наших данных в связную структуру, т.е.: хранить декартову точку как массив из двух элементов, координат x и y.

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

«Нормальный» цикл for:

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

Цикл forEach:

Под циклом я на самом деле подразумеваю метод, так как цикл forEach — это метод прототипа Array, следовательно, это не цикл в классическом понимании понятия (от него нельзя оторваться); Поскольку это метод, он фактически требует перебора коллекции, поэтому мы не можем просто выйти из простого числового диапазона. Метод forEach принимает обратный вызов в качестве параметра, а этот параметр принимает параметр, который является каждым элементом коллекции.

Цикл for..of

Этот цикл, аналогичный циклу forEach, перебирает коллекцию. На самом деле он проходит через каждое значение объекта. Таким образом, Object.values(obj).forEach даст тот же результат, что и for of obj. Поскольку массив — это не что иное, как объект, в котором его ключами являются индексы, а значения — фактические значения, мы можем использовать цикл for..of в массиве;

Цикл for..in

Этот цикл противоположен циклу for..of, вместо того, чтобы перебирать Object.values ​​объекта, он перебирает ключи указанного объекта. Таким образом, цикл for..in будет аналогичен использованию Object.keys(obj).forEach;

Итак, эти петли действительно крутые и все такое, но какой из них я должен использовать ?? Как и большинство вещей, связанных с информатикой, это зависит :((

С точки зрения производительности

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

Чтобы запустить эти тесты, я изменил приведенные выше сценарии, чтобы суммировать массив из 1 миллиона элементов (1 миллион единиц). Чтобы увидеть, какой из них будет самым быстрым;

Полученные результаты:

Все результаты даны в секундах, и они были получены на Ryzen 5 с 16 ГБ ОЗУ при работе с Ubuntu 20.08. Эти тайминги были получены с помощью команды POSIX time и узла v18.12.0;

Глядя на эти результаты, мы видим, что на самом деле не имеет значения, какой цикл мы выбираем: простой, forEach или forOf. Но мы должны избегать использования циклов forIn для такого рода операций.

Хорошо, но почему?

Есть три причины, по которым вы не должны использовать forIn для перебора элементов массива:

  • forIn будет перебирать все принадлежащие и унаследованные свойства массива, которые не помечены как DontEnum, поэтому, если кто-то добавит свойства к конкретному объекту массива или изменит его прототип, новые свойства также будут повторяться, вызывая нежелательный побочный эффект. ;
  • forIn не гарантирует сохранение порядка элементов
  • это медленно, потому что вам нужно просмотреть все свойства объекта массива и всю его цепочку прототипов, и вы все равно получите только имя свойства, IE. чтобы получить значение, потребуется дополнительный поиск

Заключение

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