Объясните поведение этого JavaScript-кода: console.log(x); var x = 5; function f(){console.log(y);} f(); var y = 3; Почему вывод такой, и как это связано с hoisting и областями видимости
Вывод будет: undefined undefined Почему так: 1) Hoisting (поднятие): - До выполнения кода движок поднимает объявления в текущую область (глобальную): - `var x` — объявляется и инициализируется значением `undefined`. - `var y` — то же самое: `undefined`. - `function f` — функция полностью поднимается (ее тело доступно сразу). 2) Выполнение пошагово: - `console.log(x)` — печатает текущее значение `x`, то есть `undefined`. - `x = 555` — теперь `x` получает значение 555. - `f()` — внутри `f` делается `console.log(y)`. Переменная `y` найдена в глобальной области, но пока ей присвоено только `undefined` (присвоение ниже), поэтому печатается `undefined`. - `y = 333` — теперь `y` становится 333 (уже после вызова `f`). 3) Области видимости: функция `f` использует лексический (глобальный) scope, т.е. ищет `y` во внешней области; поскольку `y` была объявлена через `var`, её объявление было поднято, но инициализация выполнена позже. Замечание: если бы `x`/`y` были объявлены через `let`/`const`, доступ до их инициализации привёл бы к ReferenceError (TDZ), а не к `undefined`.
undefined
undefined
Почему так:
1) Hoisting (поднятие):
- До выполнения кода движок поднимает объявления в текущую область (глобальную):
- `var x` — объявляется и инициализируется значением `undefined`.
- `var y` — то же самое: `undefined`.
- `function f` — функция полностью поднимается (ее тело доступно сразу).
2) Выполнение пошагово:
- `console.log(x)` — печатает текущее значение `x`, то есть `undefined`.
- `x = 555` — теперь `x` получает значение 555.
- `f()` — внутри `f` делается `console.log(y)`. Переменная `y` найдена в глобальной области, но пока ей присвоено только `undefined` (присвоение ниже), поэтому печатается `undefined`.
- `y = 333` — теперь `y` становится 333 (уже после вызова `f`).
3) Области видимости: функция `f` использует лексический (глобальный) scope, т.е. ищет `y` во внешней области; поскольку `y` была объявлена через `var`, её объявление было поднято, но инициализация выполнена позже.
Замечание: если бы `x`/`y` были объявлены через `let`/`const`, доступ до их инициализации привёл бы к ReferenceError (TDZ), а не к `undefined`.