Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Область видимости let и var. Что меняет внутренняя функция? (https://javascript.ru/forum/misc/80541-oblast-vidimosti-let-i-var-chto-menyaet-vnutrennyaya-funkciya.html)

Launder 18.06.2020 17:00

Область видимости 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 и уходим в бесконечный цикл.:dance:

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

Nexus 18.06.2020 17:52

Эту статью читали?
https://learn.javascript.ru/let-const

Launder 20.06.2020 22:44

Как сказать-то... Из серии, "а слона-то я и не заметил" :)
Тут же функция bar лежит в корне функции foo, а вызывается не из корня, а из блока for, вот bar ищет сначала внутри себя, затем в корне функции foo(в цикл for не заходит (а в случае var переменная поднялась бы в корень функции foo) ), а затем идёт в глобальную зону видимости. Ну а далее как я описал в предыдущем сообщении.
Сорри.


Часовой пояс GMT +3, время: 01:18.