Итераторы

Давайте рассмотрим, какой способ перебора элементов будет максимально быстрым в JavaScript. У нас есть несколько возможностей для реализации цикла, ниже приведен полный вариант кода для тестирования.

<!-- набор элементов для результатов тестирования -->
<p id="test1"></p>
<p id="test2"></p>
<p id="test3"></p>
<p id="test4"></p>
<p id="test5"></p>
<p id="test6"></p>
 
<script type="text/javascript">
// выбираем все элементы из DOM-дерева
var items = document.getElementsByTagName("*");// кэшируем текущий размер DOM-дерева
var length = items.length;
// запоминаем текущий момент времени
var time = new Date().getTime();

// запускаем первый тест, обычный перебор элементов массива,// запускается 10000 раз
for (varj=0; j<10000; j++) {
        for (var i=0; i<items.length; i++) {
               var item = items[i];
        }
}
// выводим результат в подготовленный выше контейнер
document.getElementById('test1').innerHTML = 
        "Простойцикл: " + (new Date().getTime() - time);

time = new Date().getTime();

// кэшируем размер массива
for (var j=0; j<10000; j++) {
        for (var i=0; i<length; i++) {
               var item = items[i];
        }
}
document.getElementById('test2').innerHTML =
        "Простойцикл (скэшированием): " + (new Date().getTime() - time);

time = new Date().getTime();

// встроенный for-in итератор для объекта массива
for (var j=0; j<10000; j++) {
        for (var i in items) {
               var item = items[i];
        }
}
document.getElementById('test3').innerHTML =
        "Простойчерез for-in: " + (new Date().getTime() - time);

time = newDate().getTime();

// обратный перебор элементов массива
for (var j=0; j<10000; j++) {
        for (var i = length - 1; i >= 0; i--) {
               var item = items[i];
        }
}
document.getElementById('test4').innerHTML =
        "Обратный: " + (new Date().getTime() - time);

time = new Date().getTime();

// итератор do-while
for (var j=0; j<10000; j++) {
        var i = 0;
        do {
               var item = items[i];
               i++;
        } while (i < length)
}
document.getElementById('test5').innerHTML =
        "do-while: " + (new Date().getTime() - time);

time = new Date().getTime();

// обратный while (самый быстрый)
for (var j=0; j<10000; j++) {
        var i = length - 1;
        while (--i) {
               var item = items[i];
        }
}
document.getElementById('test6').innerHTML =
        "Обратный while: " + (new Date().getTime() - time);
</script>

В результате мы получим примерно следующую таблицу (табл. 7.3).

БраузерОбычныйС кэшемfor-inОбратныйdo-whileОбратный while
Firefox 3.0.3714657835280297217
Safari 3.1.2141 140157 125 12593
Opera 9.61 188 125 765 94 94 78
IE 6 1281 1219 1094 468 500 360
IE 7 1391 1297 1250 515 532 406
IE 8b2 954 906 922 406 422 328
Chrome 0.2 288 246 332 117 114 95

Таблица 7.3. Различные варианты перебора массива, результаты в миллисекундах

В общем случае применение обратного while для перебора цикла в 2–3 раза быстрее всех остальных вариантов. Если веб-приложение оперирует массивами порядка 1000 элементов, то в результате применения оптимизированных приемов будет заметен значительный прирост производительности.