Почему итерация массива назад быстрее, чем вперед - PullRequest
50 голосов
/ 31 декабря 2011

С учетом этого кода:

var arr = [];

for (var i = 0; i < 10000; ++i)
    arr.push(1);

Вперед

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

В обратном направлении

for (var i = arr.length - 1; i >= 0; --i) {}

Жестко запрограммированный вперед

for (var i = 0; i < 10000; ++i) {}

Почему обратный путь намного быстрее?

Вот тест: http://jsperf.com/array-iteration-direction

Ответы [ 7 ]

81 голосов
/ 31 декабря 2011

Поскольку ваше форвард-условие должно каждый раз получать свойство length вашего массива, тогда как другое условие должно проверять только «больше нуля», очень быстрая задача.

Когда длина вашего массива не изменяется во время цикла, и вы действительно смотрите на ns-perfomance, вы можете использовать

for (var i=0, l=arr.length; i<l; i++)

Кстати: вместо for (var i = arr.length; i > 0; --i) вы можете использовать for (var i = arr.length; i-- > 0; ), который действительно проходит через ваш массив от n-1 до 0, а не от n до 1.

8 голосов
/ 31 декабря 2011

Поскольку в первой форме вы обращаетесь к свойству length массива arr один раз для каждой итерации, тогда как во второй вы делаете это только один раз.

6 голосов
/ 31 декабря 2011

Если вы хотите, чтобы они были в том же темпе, вы можете сделать это для прямой итерации;

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

Итак, вашему скрипту не нужно брать длину массива на everystep.

4 голосов
/ 31 декабря 2011

Я не совсем уверен в этом, но вот мое предположение:

Для следующего кода:

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

Во время выполнения после каждого цикла вычисляется длина arr.lengthпроходить.Это может быть тривиальной операцией, когда она стоит одна, но может иметь влияние, когда речь идет о множественных / огромных массивах.Можете ли вы попробовать следующее:

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

В приведенном выше коде мы вычисляем длину массива только один раз и работаем с этим вычисленным числом, а не выполняем вычисление длины снова и снова.

Опять же, просто высказываю свои мысли здесь.Действительно интересное наблюдение!

2 голосов
/ 31 декабря 2011

i > 0 быстрее, чем i < arr.length и происходит на каждой итерации цикла.

Вы можете уменьшить разницу следующим образом:

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

Это все еще не так быстро, как обратный элемент, но быстрее, чем ваш вариант пересылки.

1 голос
/ 31 декабря 2011

сделайте это, как показано ниже, это будет работать так же. потому что arr.length занимает время в каждой итерации вперед.

int len = arr.length;

вперед

for (var i = 0; i < len; ++i) {
}

назад

for (var i = len; i > 0; --i) {
}
1 голос
/ 31 декабря 2011

И это одинаково хорошо:

var arr= [], L= 10000;
while(L>-1) arr[L]= L--;

ИЛИ

var arr= [], i= 0;
while(i<10001) arr[i]=i++;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...