Непонятный результат простого цикла - PullRequest
1 голос
/ 13 апреля 2020

У меня есть некоторая путаница с результатом этого простого: l oop

for (var i = 0; i < 10; i++) {
  console.log(i);
}

console.log выводит значение i от 0 до 9.

Однако, когда я проверяю значение i, инструменты разработчика в браузере дают мне 10.

Может кто-нибудь объяснить мне, почему значение i здесь 10? Условие в моем l oop (i < 10) не позволяет ему go более 9.

Я бы получил это, если бы я l oop массив здесь. Я хотел бы иметь значения индекса и array.length, который всегда выше, чем самый высокий номер индекса.

Так может кто-нибудь объяснить мне, что происходит?

[ОБНОВЛЕНИЕ] Спасибо за ваш немедленный ответ и помощь, ребята! Я проголосовал за каждый правильный ответ. Но «зеленая галочка» досталась человеку, который первым дал исчерпывающий ответ.

Ответы [ 4 ]

2 голосов
/ 13 апреля 2020

Важно понять назначение каждого из 3 (необязательных) выражений в for-l oop:

1) выражение инициализации

Выражение (включая выражения присваивания) или объявление переменной, вычисляемое один раз до начала l oop. Обычно используется для инициализации переменной счетчика. Это выражение может опционально объявлять новые переменные с помощью переменных var или let. Переменные, объявленные с помощью var, не являются локальными для l oop, т. Е. Они находятся в той же области, в которой находится l oop. Переменные, объявленные с помощью let, являются локальными для оператора. Результат этого выражения отбрасывается.

2) выражение условия

Выражение, которое будет оцениваться перед каждой итерацией l oop. Если это выражение имеет значение true, оператор выполняется. Этот условный тест не является обязательным. Если опущено, условие всегда оценивается как истинное. Если выражение оценивается как ложное, выполнение переходит к первому выражению после конструкции for.

3) final-expression

Выражение для оценивать в конце каждой итерации l oop. Это происходит до следующей оценки состояния. Обычно используется для обновления или увеличения переменной счетчика.

Исходя из этих определений, очевидно, что когда i == 9 выражение условия оценивается как true, следовательно, ваше конечное выражение будет выполняться. Видя, как конечное выражение увеличивает i на 1, 9 затем становится 10.

2 голосов
/ 13 апреля 2020

Это

for (var i = 0; i < 10; i++) {
  console.log(i);
}

примерно эквивалентно

var i = 0;
while ( i < 10 )
{
  console.log(i);
  i++;
}

Как видите, сначала проверяется условие l oop, затем выполняется увеличение. В конце l oop, когда i == 9, l oop вычисляется в последний раз, i увеличивается и условие больше не выполняется.

Таким образом, i равно 10, когда l oop заканчивается.

2 голосов
/ 13 апреля 2020

Вы устанавливаете l oop так, чтобы i увеличивалось до тех пор, пока условие не станет истинным.

Вот как работает for-l oop:

  1. Выполнить инициализатор (i=0)
  2. Проверить условие (равно i <10?)
  3. Если true, выполнить код в l oop (console.log(i))
  4. Выполнить действие post l oop, в данном случае i++
  5. Повторить с точка 2 до тех пор, пока условие больше не будет истинным

Когда i=9, условие выполняется в последний раз (2), код в l oop выполняется (3), сообщение l oop действие выполнено, так что i=10 (4), условие проверяется снова и l oop прекращается, так как условие больше не выполняется.

Но теперь i=10.

2 голосов
/ 13 апреля 2020

Вы уже как бы ответили на свой вопрос:

Ваше условие l oop отменяет l oop, когда i < 10 больше не выполняется. Итак, если подумать об этом, i должно быть 10 или выше, чтобы l oop мог прервать! Следовательно, вы видите i с 10 в конце.

Вот что происходит:

  • ...
  • i равно 9
  • i < 10 верно
  • Ваше тело l oop выполняется (в последний раз)
  • i++ выполняется, делая i 10
  • i < 10 больше не верно
  • Ваш l oop прерван
  • Теперь, глядя на i, вы видите 10, потому что он получил это значение 3 шаги, описанные выше в моем объяснении

И если вам интересно, как вы можете видеть i вне l oop: это потому, что var создает переменные в функциональной области. i доступно во всей функции, даже до вашего l oop (там это undefined) и после. Чтобы создать блочную переменную, вы можете использовать вместо нее let.

Весь этот процесс можно очень четко увидеть в отладчике, если вы шагаете по коду (посмотрите на вывод консоли, текущую позицию и переменное содержимое i в области часов справа):

gif

...