Показать сообщение отдельно
  #1 (permalink)  
Старый 18.06.2020, 17:00
Интересующийся
Отправить личное сообщение для Launder Посмотреть профиль Найти все сообщения от Launder
 
Регистрация: 25.04.2019
Сообщений: 19

Область видимости let и var. Что меняет внутренняя функция?
Вот такой код:
function foo() 
   {
       function bar(a)
             {
		    i = 3;
		    alert( a + i );
	     }

       for (let i=0; i<7; i++) 
             {
		    bar( i * 2 );
                    alert(`i = ${i}`); // смотрим меняет ли i функция
	     }
   }
foo();

Если поменять в for, let на var, то логика работы программы будет понятна:
1. функция foo создала функцию bar и запустила цикл for.
2. i = 0, запускается bar, a = i*2 = 0.
3. на первом же шаге исполнения, происходит операция i = 3. Поскольку переменная внутри функции не объявлена, то она идёт вверх, к месту своего создания (функция foo), и ищет переменную внутри неё, находит, присваивает ей 3.
3. считает 0 + 3, выводит 3.
4. bar заканчивает свою работу, следующий alert - служебный, чтоб проконтролировать текущее значение переменной, он, естественно выдаёт 3, и после окончания цикла (или вначале следующего?) происходит инкремирование i, и он становится равным 4.
5. первая операция a = i*2 (в скобках bar) даёт нам а = 8.
6. дальше i принудительно снова становится равным трём соответственно выводится 8 + 3 = 11.
7. убеждаемся что i у нас по прежнему равно трём, заканчиваем, инкримируем i, снова получаем 4 и уходим в бесконечный цикл.

Всё это прекрасно, но с let подобного не происходит. Почему?
Проверка alert после завершения bar, говорит нам о том, что то, что происходит внутри bar не влияет, на значение i в цикле. Почему?
Вот эта строчка внутри bar: i = 3 - не объявляет новую переменную. А значит она должна идти вовне, находить там текущий i = 0, и присваивать ему значение 3. Но она почему-то этого не делает. Почему? А делает она следующее: каким-то образом "проскальзывает" мимо объявленного i в цикле, топает в глобальную область видимости, и объявляет глобальную переменную i, и, в дальнейшем, bar уже взаимодействует с этой переменной, в глобальной области видимости. Если мы, после завершения работы foo, выведем alert(i), ничего не объявляя, то программа выведет 3, значение из функции bar.
Кстати, если функции bar не будет, а все эти операции делать внутри цикла, то поведение будет, аналогичное var.
Объясните, пожалуйста, логику работы let, в этом примере.
Спасибо!

Последний раз редактировалось Launder, 20.06.2020 в 22:32.
Ответить с цитированием