Замыкания в JavaScript

Замыкания в JavaScript

В этом уроке вы узнаете, что такое замыкание в JavaScript и как оно работает.

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

В главе о функциях JavaScript вы узнали, что в JavaScript область действия переменной может быть глобальной или локальной. Начиная с ES6, вы также можете создавать переменные в области блока, используя ключевое слово let.

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

Однако существуют определенные ситуации, когда вы хотите, чтобы переменная была доступна по всему сценарию, но вы не хотите, чтобы какая-то часть вашего кода могла случайно изменить ее значение.

Давайте посмотрим, что произойдет, если вы попытаетесь добиться этого с помощью глобальной переменной:

// Глобальная переменная
var counter = 0;

// Функция для работы с переменной 'counter'
function makeCounter() {
  return counter += 1;
}

// Вызов функции
makeCounter();
console.log(counter); // Результат: 1

makeCounter();
console.log(counter); // Результат: 2

// Попытка изменения переменной 'counter' снаружи
counter = 10;
console.log(counter); // Результат: 10

Как видно из приведенного выше примера, значение переменной counter можно изменить из любой точки программы, не вызывая функцию makeCounter().

Теперь давайте попробуем добиться того же с локальной переменной и посмотрим, что произойдет:

function makeCounter() {
  // Локальная переменная
  var counter = 0;

  // Увеличение значения локальной переменной
  return counter += 1;
}

// Вызов функции
console.log(makeCounter()); // Результат: 1
console.log(makeCounter()); // Результат: 1

В этом случае переменной счетчика нельзя манипулировать извне, поскольку она является локальной для функции makeCounter(), но ее значение также не будет увеличиваться после последующего вызова функции, поскольку каждый раз, когда мы вызываем функцию, она сбрасывает значение переменной счетчика. Замыкание JavaScript может решить нашу проблему.

Замыкание - это внутренняя функция, которая имеет доступ к области видимости родительской функции, даже после того, как родительская функция закончила выполнение. Это достигается созданием функции внутри другой функции. Давайте посмотрим на следующий пример, чтобы увидеть, как это работает:

function makeCounter() {
  var counter = 0;

  // Внутренняя функция
  function make() {
    counter += 1;
    return counter;
  }
  return make;
}

/* Выполнить функцию makeCounter() и сохранить
возвращенное значение в переменной myCounter */
var myCounter = makeCounter();

console.log(myCounter()); // Результат: 1
console.log(myCounter()); // Результат: 2

Как вы можете видеть в приведенном выше примере, внутренняя функция make() возвращается из внешней функции makeCounter(). Таким образом, значением myCounter является внутренняя функция make(), и вызов myCounter вызывает make(). В JavaScript функции могут быть назначены переменным, переданы в качестве аргументов другим функциям, могут быть вложены в другие функции и т.д.

Вы также можете видеть, что внутренняя функция make() все еще может получить доступ к значению переменной counter, определенной во внешней функции, даже если функция makeCounter() уже завершила выполнение. Это происходит потому, что функции в JavaScript формируют замыкания. Замыкания внутренне хранят ссылки на их внешние переменные и могут получать доступ и обновлять их значения.

В приведенном выше примере функция make() является замыканием, код которого ссылается на счетчик внешней переменной. Это подразумевает, что всякий раз, когда вызывается функция make(), код внутри нее может обращаться к переменной счетчика и обновлять ее, потому что она хранится в замыкании.

Наконец, поскольку внешняя функция завершила выполнение, никакая другая часть кода не может получить доступ к переменной счетчика или манипулировать ею. Только внутренняя функция имеет доступ к ней.

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

// Пример с анонимной функцией
var myCounter = (function() {
  var counter = 0;

  // Внутренняя анонимная функция
  return function() {
    counter += 1;
    return counter;
  }
})();

console.log(myCounter()); // Результат: 1
console.log(myCounter()); // Результат: 2

Создание функций геттер (getter) и сеттер (setter)

Здесь мы создадим переменную secret и защитим ее от прямого манипулирования извне кода с помощью замыкания. Мы также создадим функции геттер и сеттер для получения и установки его значения.

Кроме того, функция setter также выполнит быструю проверку, является ли указанное значение числом или нет, и если это не так, оно не изменит значение переменной.

var getValue, setValue;

// Самовыполняющаяся функция
(function() {
  var secret = 0;

  // Функция геттер
  getValue = function() {
    return secret;
  };

  // Функция сеттер
  setValue = function(x) {
    if(typeof x === "number") {
      secret = x;
    }
  };
}());

// Вызов функции
getValue(); // Результат: 0
setValue(10);
getValue(); // Результат: 10
setValue(null);
getValue(); // Результат: 10

Оставьте первый комментарий

Оставить комментарий

Ваш электронный адрес не будет опубликован.


*