Понимание замыканий в JavaScript


Введение

Согласно нашему дружелюбному соседу-учителю MDN Docs:

Замыкание — это комбинация функции, собранной вместе (заключенной) со ссылками на ее окружающее состояние (лексическое окружение).

Функция + ее лексическое окружение = замыкание

Прежде всего

Теперь мы знаем, что такое функция, и для того, чтобы полностью понять Closures, нам сначала нужно понять Lexical Environment.

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

Итак, теперь вы знаете, как работает лексическая область видимости.

TL;DR — внутренние функции могут использовать переменные и функции родительской/внешней функции.

Это можно показать на очень простом примере:

function greet() {
  const userName = "Maitra";
  function greetMsg() {
    console.log("Welcome,", userName);
  }
  greetMsg();
}
greet(); //output: Welcome, Maitra
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь, что если мне нужно извлечь внутреннюю функцию и использовать ее как независимую функцию. Сможет ли она тогда получить доступ к переменной userName из своей родительской функции?

Ответ — ДА!!! и причина в Closures !!!!.

Закрытия

Вы не верите мне? Попробуйте сами:

function greet() {
  const userName = "Maitra";
  return function greetMsg() {
    console.log("Welcome,", userName);
  };
}
const displayMsg = greet();
console.log(displayMsg); //output: ƒ greetMsg() {}
console.log(displayMsg());//output: Welcome, Maitra
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Как видите, displayMsg — это не что иное, как функция greetMsg, но самое интересное здесь то, что функция displayMsg не упоминает константу userName, но при вызове печатает ее значение.

Хотя, извлекая внутреннюю функцию, мы видим, что функция одна, но она всегда идет со своим лексическим окружением (т.е. своя лексическая область видимости + лексическая область видимости ее родителя).

Вот и все, самое простое объяснение того, что такое Closure. Мы также можем сказать следующее:

Closure — это функция, которая запоминает переменные из того места, где она была определена, независимо от того, где она будет выполняться позже.

Немного веселья ft. Doremon

Теперь я хочу немного повеселиться, и поэтому я подготовил этот забавный пример, в котором используется Closure.

function pocket() {
  const strengthPill = true;
  function doremon() {
    return function nobita() {
      function fightGian() {
        if (strengthPill) {
          console.log("win");
        } else {
          console.log("lose");
        }
      }
      fightGian();
    };
  }
  return doremon();
}
const nobitaAlone = pocket();
console.log(nobitaAlone); //output: ƒ nobita() {}
console.log(nobitaAlone()); //output: win
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы видим, что только если у nobita есть strengthPill, то он может победить Gian. И как обычно nobita находится под защитой doremon и имеет доступ к strengthPill. Но что делать, если его извлекли и он остался один?

Как мы видим в функции nobitaAlone, у нас есть только функция nobita и нет упоминания о strengthPill, так что технически он должен проиграть. Но благодаря Закрытию nobita все еще имеет доступ к strengthPill и может победить Джиана 🥳.

Надеюсь, вы узнали что-то новое и получили удовольствие от игры. Если да, то заходите в гости:

  • мои другие блоги
  • мои проекты

И не забудьте следовать за мной 🙂

Оцените статью
Procodings.ru
Добавить комментарий