Alxblsk.com Logo
RE•DONE
Blog by Aliaksei Belski

Используем замыкания на полную

Published: May 8th, 2017, Updated: September 12th, 2020closurejavascript

Используем замыкания на полную

Если вы слышите слово "замыкание" впервые, оно может заставить вас нервничать. Но не стоит волноваться. На самом деле, замыкание - это просто. Для того, чтобы понять, как работает замыкание, необходимо вспомнить, что является областью видимости в Javascript. Вопрос с подвохом, так как для ключевого слова var это строго функция, а для let - любой функциональный блок. Для примера используем var, которая используется внутри какой-либо функции:

function iterator() {
  var counter = 0;
}

Как мы знаем, переменная, объявленная внутри определенной области видимости, не будет доступна извне. В случае, если такая переменная уже существует в родительской области видимости, она будет переобъявлена. Что же касается всех последующих дочерних областей видимости, переменная counter в них будет доступна. К примеру, давайте внутри нашей функциии iterator мы собъявляем в качестве возвращаемого значения другую функцию:

function iterator() {
  var counter = 0;

  return function increment() {
    return ++counter;
  }
}

Обратите внимание, что переменная counter не была переобъявлена, но была переиспользована. Внутри функции increment мы пользуемся поступностью переменной, объявленой в более высокой области видимости. И самое интересное: давайте воспользуемся написанным выше кодом:

var counterValue;
var increment = iterator();

counterValue = increment(); // 1
counterValue = increment(); // 2
counterValue = increment(); // 3

В результате вызова функции iterator(), нам предоставилась возможность использовать функцию increment() в другой области видимости. При этом, оригинальная функция iterator() продолжила иметь доступ к переменной counter в области видимости, где она была объявлена.

Ситуация, в которой функция может использовать переменные области видимости, внутри которой она была объявлена, и называется замыканием.

Для того, чтобы сделать наш модуль переиспользуемым, давайте его модифцируем:

function iterator(initialValue) {
  var counter = initialValue || 0;

  return {
    inc:   function() { counter++; },
    dec:   function() { counter--; },
    val:   function() { return counter; },
    reset: function() { counter = 0; }
  }
}

Благодаря данной модификации, будет возможно уменьшать и даже сбрасывать счетчик, причем каждая из трех объявленных функций будет иметь доступ к переменной counter.

var counterValue;
var iterate = iterator(4); // Устанавливаем начальное значение счетчика

iterate.inc(); // 5
iterate.dec(); // 4
iterate.reset(); // 0
iterate.inc(); // 1

console.log(iterate.val());

Итог

  • Замыкание в Javascript встречается повсеместно. Чтобы получить замыкание, достаточно объявить одну функцию внутри другой.
  • С помощью замыкания можно организовать приватный доступ к данным.