В этом уроке я хочу рассказать о том, что такое цепь областей видимости.
У нас имеется следующий код:
function b() {
console.log(user);
}
function a() {
var user = "qqc";
b();
}
var user = "golos";
a();
Скрипт почти такой, как и в предыдущем уроке, разве что убрали объявление переменной user из функции b и оставили лишь один вывод в консоль. Как думаете, что отобразится в консоли?
Немного вспомним: когда вызывается функция b, создаётся новый контекст выполнения, кладётся в стек вызовов, а все объявленные переменные отправляются в переменное окружение (variable environment). Но, в нашем случае, переменная u в функции b, где мы хотим её отобразить, не объявлена.

Неожиданно, правда? А где жеundefined? Ну илиqqc, ведь это было последним присвоением перед вызовом функцииb?
В консоли мы увидели golos - значение переменной, "живущей" на глобальном уровне.
Когда мы обращаемся к переменной, JavaScript не просто просматривает переменное окружение в текущем контексте выполнения. Я уже упоминала мельком понятие внешнего окружения.
Получается, когда интерпретатор пытается получить доступ к переменной, он сначала проверяет, есть ли такая переменная в текущем контексте выполения, и, если её нет, отправляется на поиски во внешнее переменное окружение. В нашем случае, на глобальном уровне.
Но почему? Ведь мы функциюbвызываем из функцииa, почему внешним окружением стал не контекст выполнения этой функции?
Лексически функция b находится в глобальном контексте выполнения, не внутри функции a. То есть на том же уровне, что и строка var user = 'golos'.

Когда мы вызываем функцию, ссылка на внешнее окружение записывается, ведь синтаксический парсер уже пробежал и запомнил, на каком уровне, где какая переменная и функция создается. Эта ссылка сохраняется в скрытом свойстве функции [[Scope]].
Такие ссылки, образующие цепочки, называются цепью областей видимости (scope chain). Напомню, что область видимости - это та часть кода, в которой мы имеем доступ к переменным.
Немного изменим код:
function a() {
function b() {
console.log(user);
}
var user = "qqc";
b();
}
var user = "golos";
a();
Мы изменили лексическое окружение функции b.

Когда мы запустим наше приложение, мы увидим в консоли qqc, потому как теперь лексически функция b "живёт" внутри функции a, соответственно, не найдя внутри себя переменной user, отправится на внешний слой - теперь это функция a.

Еще немного изменений:
function a() {
function b() {
console.log(user);
}
b();
}
var user = "golos";
a();
В консоли снова golos.

Когда выполнялась функция b, она поискала у себя переменную, отправилась искать её во внешнее окружение - в функцию a, но и там такой переменной не оказалось, и она отправилась во внешнее окружение функции a - глобальный контекст выполнения.

Голосуйте за моего делегата здесь. Для этого нужно нажать на стрелочку рядом с моим ником qqc. Спасибо за поддержку! 🙏🌸






















Привет!
Этот пост был выбран Академией Голоса и попал в список программы поддержки качественных образовательных постов.
Ссылка на твой пост будет опубликована в отчете Академии.
Спасибо за полезный контент (ノ◕ヮ◕)ノ*:・゚✧
@qqc, Поздравляю!,
Ваш пост был упомянут в моем хит-параде в следующей категории: