Чтобы понять замыкания, необходимо разобраться с тем, что такое лексическое окружение.

Лексическое окружение

<aside> 👉 Лексическое окружение – это невидимый (скрытый) объект, который есть у каждой функции, блока и скрипта в JS. Он состоит из двух частей: 1️⃣ Объект с переменными в текущей области видимости 2️⃣ Ссылка на родительское, то есть внешнее лексическое окружение

</aside>

<aside> ❗ Лексическое окружение имеет доступ к переменным внутри себя и к переменным родительского окружения

</aside>

Пример:

const x = 1;

const logToConsole = function() {
  const i = 'Hi'
	console.log(i)
}

logToConsole(); // Hi

Здесь два лексических окружения:

Первое – глобальное. В нём, во-первых, содержатся переменные x и logToConsole, а, во-вторых, ссылка на родительское окружение. Здесь – это null, так как над глобальной областью ничего нет.

Второе – локальное окружение, внутри функции logToConsole: в нём содержится одна переменная – i. А ссылка указывает на ближайшее родительское (то есть внешнее) окружение – то есть на глобальное.

Упрощенное представление:

// Глобальное окружение:
{
	ссылка: –> null,
	переменные: {x: 1, logToConsole: function}
}

// Локальное окружение (внутри logToConsole)
{
	ссылка: –> глобальное лексическое окружение,
	переменные: {i: "Hi"}
}

Второе лексическое окружение имеет доступ к переменным внутри себя И к переменным снаружи. А вот первое – только к своим переменным.

<aside> ❗ ВАЖНО: второе лексическое окружение будет создано только во время вызова функции

</aside>

Как будет выполняться код:

  1. Начинается запуск кода, создаётся пустое лексическое окружение
  2. Создаётся переменная x со значением 1 в глобальном окружении
  3. Создаётся переменная logToConsole со значением функции, тоже в глобальном окружении
  4. Вызывается logToConsole, и ТОЛЬКО ТОГДА начинает выполняться код внутри функции
    1. Для этого вызова создаётся пустое лексическое окружение
    2. Создается переменная i и добавляется в это окружение
    3. Выполняется вывод в консоль, мы выходим из функции
  5. Выполнение скрипта на этом заканчивается