Задать вопрос

Что такое «инвертированный» цикл for в JS?

Такие дела.
Читал статейку по производительности JS и наткнулся в ней на некий инвертированный цикл.
Стало интересно, что за цикл такой, гугол ничего не дал толкового, так что продолжил читать статью в надежде на объяснение.

И вот наткнулся на строки:
2fa00681687644d6af2319fdaf78b37f.png

И вообще не понял синтаксиса и механизма этого инвертированного цикла.
Кто что знает об этом?
  • Вопрос задан
  • 1599 просмотров
Подписаться 2 Оценить 4 комментария
Решения вопроса 1
bingo347
@bingo347 Куратор тега JavaScript
Crazy on performance...
Классический цикл for в javascript состоит из 3х операторов: init, predicate, nextIteration
В общей записи это выглядит так:for(init; predicate; nextIteration) { body }

Цикл for исполняется следующим образом:
1. Выполняется оператор init в области видимости блока цикла
Обычно здесь объявляют переменную-счетчик и присваивают ей начальное значение
Определение "в области видимости блока цикла" означает, что если init-оператор представляет собой оператор let - то объявленные переменные будут видны в цикле, но не за его пределами
2. Вычисляется predicate, его результат приводится к boolean и последующее выполнение зависит от результата этого приведения:
Если результат === false - то цикл завершается
Если результат === true - то переходим к шагу 3
3. Исполняется тело цикла - блок body, официально блоком быть не обязан, может быть и единичным оператором, но лучше всегда писать блок (фигурные скобки)
4. Исполняется оператор nextIteration и переходим к пункту 2

Теперь разберемся на конкретных примерах:
Прямой цикл
for(let i = 0; i < 10; i++) {
  console.log(i);
}

Объявляется переменная i и ей присваивается начальное значение 0
Получается результат выражения Boolean(i < 10) -> 0 < 10 - true -> Boolean(true) - true -> можем выполнять тело
Выполняется тело console.log(i); -> видим 0 в консольке
Выполняется i++ -> i становится 1
Получается результат выражения Boolean(i < 10) -> 1 < 10 - true -> Boolean(true) - true -> можем выполнять тело
...
Так все продолжается 10 раз, на 10 итерации появляются изменения после этого момента:
Выполняется i++ -> i становится 10
олучается результат выражения Boolean(i < 10) -> 10 < 10 - false -> Boolean(false) - false -> завершаем цикл

инвертированный цикл
for(let i = 10; i--;) {
  console.log(i);
}

Объявляется переменная i и ей присваивается начальное значение 10
Получается результат выражения Boolean(i--) -> i-- - 10, i = 9 -> Boolean(10) - true -> можем выполнять тело
Выполняется тело console.log(i); -> видим 9 в консольке
Оператор nextIteration - пустой, ничего выполнять не надо
Получается результат выражения Boolean(i--) -> i-- - 9, i = 8 -> Boolean(9) - true -> можем выполнять тело
...
Цикл по прежнему работает 10 раз, последняя итерация (когда i к моменту исполнения predicate равна 0):
Получается результат выражения Boolean(i--) -> i-- - 0, i = -1 -> Boolean(0) - false -> завершаем цикл

Как видим, за счет отсутствия nextIteration оператора, на каждой итерации выполняется на одно действие меньше, поэтому цикл отрабатывает быстрее
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
miraage
@miraage
Старый прогер
Бред сивой кобылы. DEMO.

var start1 = Date.now();
for (var i = 0; i < 1e10; ++i) {
  
}
console.log('standard', Date.now() - start1);

var start2 = Date.now();
for (var i = 1e10; i > 0; --i) {
  
}
console.log('reverse', Date.now() - start2);


"standard"
101
"reverse"
101
"standard"
101
"reverse"
101
"standard"
101
"reverse"
101
"standard"
101
"reverse"
101
Ответ написан
T_y_l_e_r
@T_y_l_e_r
В обратном порядке перебирает элементы.
В паскале есть отдельный синтакисис для этого.

for i := A to B do
  begin
    . . .
  end;

for i := A downto B    do
  begin
    . . .
  end;
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы