вторник, 18 июня 2013 г.

JavaScript Особенности написания циклов For

var i;

function initializeI () {
    if (!i) {
        i = 0;
    }
    console.log('1: Initialize I: ' + i);  
    return i;
}

function equationI () {
    if (i < 2) {
        console.log('2: Equation I: true');
        return true;
    } else {
        console.log('2: Equation I: false');
        return false;
    }
}

function incrementI () {
    i = i + 1;
    console.log('3: Increment I: ' + i);
}

for (initializeI(); equationI(); incrementI()) {
    console.log('4: Result I: ' + i);
}

console.log('5: I in the end of Loop: ' + i);

Результат выполнения кода.

// Первый шаг цикла
1: Initialize I: 0
2: Equation I: true
4: Result I: 0
3: Increment I: 1

// Второй шаг цикла
2: Equation I: true
4: Result I: 1
3: Increment I: 2

// Третий шаг цикла
2: Equation I: false

// После выполнения всего цикла
5: I in the end of Loop: 2

Цикл выполняется следующим образом:
Инициализация счетчика цикла - выражение сравнения - тело цикла - приращение в выражении инкремента.
Далее выражение сравнения - тело цикла - приращение в выражении инкремента.
И так до тех пор пока на следующем шаге цикла выражение сравнение не будет равно false. После этого выходим из цикла, не выполняя тело цикла и не выполняя приращение в выражении инкремента, так как оно обязано выполняться в конце тела цикла, как в цикле while.

Как видно из результатов выполнения кода на первом шаге цикла происходит инициализация переменной i. На следующих шагах цикла инициализация переменной больше не производится.

Далее на всех шагах цикла сперва проверяется выражение сравнения (условие цикла). Если результат сравнения равен true, то мы входит в тело цикла внутри фигурных скобок. Если результат сравнения равен false, то мы сразу выходим из цикла и выражение приращения счетчика цикла не выполняем.

После того, как выполнится тело цикла, в конце начинает выполняться выражение инкремента, после чего цикл переходит на следующий шаг.

На следующем шаге этап инициализации пропускается и сразу выполняется выражение сравнения (условие цикла). Если результат сравнения равен true, то мы входит в тело цикла внутри фигурных скобок и далее выполняем шаги по кругу: тело цикла -  приращение в выражении инкремента - следующий шаг цикла начиная с выражения сравнения и так далее.

Если результат сравнения равен false, то мы сразу выходим из цикла и выражение приращения счетчика цикла не выполняем.

Значение счетчика цикла после завершения всего цикла будет равно последнему приращению, которое было выполнено когда мы вошли в тело цикла в последний раз.

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

1: Initialize I: 0
2: Equation I: false
5: I in the end of Loop: 0

==================================================

// Если условие равно false, то внутрь цикла мы не входим и выражение после сравнения не рассчитываем.

var a = 0;

for (var i = 0; i < 0; i = i + 1, a = a + 1) { // Выражение после сравнения рассчитано не будет.
  console.log('a1: ' + a); // Сюда мы не войдем, так как условие равно false.
  console.log('i1: ' + i); // Поэтому лог выведен не будет.
}

console.log('a2: ' + a); // 0
console.log('i2: ' + i); // 0

// Если условие равно true, то внутрь цикла мы входим и выражение после сравнения рассчитываем, но только после того, как проведем все операции внутри цикла, то есть как в цикле while в самом конце тела цикла.

var a = 0;

for (var i = 0; i < 1; i = i + 1, a = a + 1) { // Выражение после сравнения рассчитано будет, но как бы после тела цикла.
  console.log('a1: ' + a); // 0 - в первый раз имеет самое первое значение, полученное до начала цикла.
  console.log('i1: ' + i); // 0 - в первый раз имеет самое первое значение, полученное до начала цикла.
}

console.log('a2: ' + a); // 1 - последнее значение, если мы вошли хотя бы раз в тело цикла сохраняется.
console.log('i2: ' + i); // 1 - последнее значение, если мы вошли хотя бы раз в тело цикла сохраняется.

Примеры.

for (var i = 2; i > 0; i--) {
  console.log(i);
}

// 2
// 1

for (var i = 2; i--;) {
  console.log(i);
}

// 1
// 0

for (var i = 2; i = i - 1;) {
  console.log(i);
}

// 1

Пример.

var i;

for (i = 0; i < 1; ++i)        {console.log('1: ' + i);} // 0
for (i = 0; i < 1; i++)        {console.log('2: ' + i);} // 0
for (i = 0; i < 1; i = i + 1) {console.log('3: ' + i);} // 0
for (i = 0; i < 1;)               {i = i + 1; console.log('4: ' + i);} // 1
for (i = 0; i < 1;)               {console.log('5: ' + i); i = i + 1;} // 0

console.log('------------------------');

for (i = 2; --i;)                 {console.log('6: ' + i);}  // 1
for (i = 1; i--;)                 {console.log('7: ' + i);}  // 0
for (i = 1; i > 0; --i)         {console.log('8: ' + i);}  // 1
for (i = 1; i > 0; i--)         {console.log('9: ' + i);}  // 1
for (i = 1; i > 0; i = i - 1) {console.log('10: ' + i);}  // 1
for (i = 2; i = i - 1;)         {console.log('11: ' + i);}  // 1
for (i = 1; i > 0;)              {i = i - 1; console.log('12: ' + i);}  // 0
for (i = 1; i > 0;)              {console.log('13: ' + i); i = i - 1;}  // 1

Комментариев нет:

Отправить комментарий