Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
qqc
8 лет назад

[JAVASCRIPT] - Урок 5 - Цепь областей видимости

В этом уроке я хочу рассказать о том, что такое цепь областей видимости.

У нас имеется следующий код:

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. Спасибо за поддержку! 🙏🌸


1
651.411 GOLOS
На Golos с November 2016
Комментарии (2)
Сортировать по:
Сначала старые