Современный 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)
andreymal
25.09.2023 11:11В какой среде это всё хоть? Когда я пытался колхозно измерять производительность циклов в Chrome и Firefox, то получал почти противоположные результаты
Aquahawk
Ну как так. Где прогрев, где вычисление отклонения? Поменяйте тесты местами и очень удивитесь. Поставьте быстрейший do...while в начало и получите что он станет почти самым медленным. Про кеширование длины и префискные постфиксные формы вообще молчу. Скройте статью и не позорьтесь, а сами сходите посмотрите видосы из этого плейлиста, он конечно старенький, но ничуть актуальности не утратил https://www.youtube.com/playlist?list=PLarlUwZRmTK6ptk3MtivPgcMikbYSKFnO и начните с этого
aleksandy
Зачем? Статья опубликована, галочка преподавателем поставлена, а содержание... да кого вообще волнуют подобные мелочи?