Современный JS предоставляет множество способов перебора массива. Но какой из них является наиболее эффективным по скорости?

Чтобы ответить на этот вопрос, мы проведем тесты, перебирая массивы разной длины и вызывая для каждого элемента метод toString().

Рассмотрим основные способы перебора: for, for(reverse), while, do..while, for..in, for..of, for..each.

Важно! Точность результата console.time() сильно зависит от конфигурации вашей системы.

Для начала протестируем скорость каждого способа на массиве из 1000 элементов.

const iterations = 1000;

const array = new Array(iterations).fill(0);

console.log("Длина массива", + array.length);

//for
console.time("for");
for (let i = 0; i < array.length; i++) {
array[i].toString();
}
console.timeEnd("for");

//forReverse
console.time("for(reverse)");
for (let i = array.length - 1; i >= 0; i--) {
array[i].toString();
}
console.timeEnd("for(reverse)");

//while
console.time("while");
let i = 0;
while (i < array.length) {
array[i].toString();
i++;
}
console.timeEnd("while");

//do...while
console.time("do...while");
let j = 0;
do {
array[j].toString();
j++;
} while (j < array.length);
console.timeEnd("do...while");

//for...in
console.time("for...in");
for (let k in array) {
k.toString();
}
console.timeEnd("for...in");

//for...of
console.time("for...of");
for (let l of array) {
l.toString();
}
console.timeEnd("for...of");

//for...each
console.time("for...each");
array.forEach((el) => {
el.toString();
});
console.timeEnd("for...each");

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

После проведения тестирования мы не можем однозначно назвать самый быстрый способ перебора массива, так как победители меняются в зависимости от размера массива. Однако, стандартный for цикл, for(reverse) цикл, while цикл и do...while цикл будут наилучшим выбором, так как они работают практически одинаково быстро в большинстве случаев.

Рекомендуется использовать префиксные операторы (--i, ++i) вместо постфиксных (i--, i++), так как постфиксные операторы требуют создания временной копии переменной, что занимает дополнительное время на вычисление значения выражения. В свою очередь, префиксный оператор изменяет значение переменной непосредственно в момент выполнения операции, без создания временной копии, что делает его более эффективным и быстрым.

Также для улучшения скорости необходимо кэшировать длину массива заранее.

const arrayLength = array.length;
for (let i = 0; i < arrayLength; i++) {
	array[i].toString();
}

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

Комментарии (5)


  1. Aquahawk
    25.09.2023 11:11
    +8

    Ну как так. Где прогрев, где вычисление отклонения? Поменяйте тесты местами и очень удивитесь. Поставьте быстрейший do...while в начало и получите что он станет почти самым медленным. Про кеширование длины и префискные постфиксные формы вообще молчу. Скройте статью и не позорьтесь, а сами сходите посмотрите видосы из этого плейлиста, он конечно старенький, но ничуть актуальности не утратил https://www.youtube.com/playlist?list=PLarlUwZRmTK6ptk3MtivPgcMikbYSKFnO и начните с этого


    1. aleksandy
      25.09.2023 11:11
      +1

      Скройте статью

      Зачем? Статья опубликована, галочка преподавателем поставлена, а содержание... да кого вообще волнуют подобные мелочи?


  1. andreymal
    25.09.2023 11:11

    В какой среде это всё хоть? Когда я пытался колхозно измерять производительность циклов в Chrome и Firefox, то получал почти противоположные результаты


  1. nin-jin
    25.09.2023 11:11
    -1

    1. deamondz
      25.09.2023 11:11

      у меня хром падает на этой странице (macbook air M1 2020)

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