• Теория
  • Теория

Замыкания

Код действительно работает. В чём секрет такой странной записи и что она вообще означает?

var collectContainer = function () {
  var food = 'макароны';
  var eatDinner = function () {
    console.log('Поел ' + food);
  }
  return eatDinner;
};

var schoolkid = collectContainer();
schoolkid();
// Выведет: Поел макароны

Мы хотим, чтобы функция получила фиксированное значение, которое бы не зависело от изменений в глобальной области видимости. При этом результат работы функции мы хотим получить не сразу. Как с событиями, когда мы создаём обработчик, но ждём выполнение события не сразу. В нашем примере мы собираем школьнику контейнер с едой, чтобы он мог перекусить любимыми макаронами независимо от того, что дают в столовой.

Код из примера работает так: мы вызываем collectContainer → функция collectContainer возвращает eatDinner → вызываем eatDinner.

Мы создаём функцию внутри функции. Таким образом мы создаём одну область видимости внутри другой области видимости. У eatDinner своя область видимости, в которой идёт обращение к переменной food. Эта переменная объявлена внутри collectContainer, у которой своя область видимости.

Функция eatDinner не находит внутри себя создание переменной food, смотрит в соседнюю область видимости (в область видимости collectContainer). Там она находит переменную food, узнаёт, что её значение равно строке 'макароны', и фиксирует это значение в памяти.

Постойте! Мы же выводили в консоль переменную schoolkid и там не было никаких макарон!

var collectContainer = function () {
  var food = 'макароны';
  var eatDinner = function () {
    console.log('Поел ' + food);
  };
  return eatDinner;
};

var schoolkid = collectContainer();
console.log(schoolkid);
// Выведет: function () { console.log('Поел ' + food); }

Всё верно. Код самой функции не меняется, просто в памяти вместе с функцией хранится то значение переменной, которое было при объявлении этой функции. Поэтому eatDinner «помнит» значение food. Это особенность функций, они помнят своё окружение в момент своего создания. В таком случае говорят о замыкании. Замыкание — функция, которая помнит о своём окружении. То есть это функция + все значения переменных вне локальной области видимости этой функции. Речь идёт только о переменных, которые функция использует в своём коде.

В нашем примере функция eatDinner вместе с переменной food являются замыканием.

Именно благодаря замыканиям код из примера выше работает. eatDinner помнит о значении food при своём создании, поэтому использует это значение в момент вызова. Как если бы мама сказала нам купить картошки, когда мы будем идти мимо магазина. Мы запомнили про картошку и пошли по своим делам. Когда мы увидели магазин, мы вспомнили, что именно картошка была нужна, мы её купили и пошли домой.

Убедимся, что замыкания позволяют школьнику есть макароны из контейнера независимо от еды в столовой.

Минимальный вид табов
  • index.html
HTML
HTML

Вы перешли на другую страницу

Кликните внутри мини-браузера, чтобы поставить фокус в это окно.

100%
Бабушка Кекс

Притормози, дружище

Проходить вызовы части «Знакомство с событиями» тренажёра «Погружение в браузерный JavaScript» можно после регистрации и оформления подписки.