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

Что такое Лексическая область?

Лексическая область видимости относится к видимости переменных в определенной части кода. Другими словами, речь идет о том, какие переменные доступны в данной точке кода. Область действия переменной определяется тем, где она объявлена.

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

function outer() {
  const a = 1;
  function inner() {
    const b = 2;
    console.log(a + b);
  }
  inner();
}
outer();

В этом примере из-за лексической области видимости переменная a объявлена ​​во внешней функции и доступна внутренней функции. Однако переменная b объявлена ​​во внутренней функции и недоступна для внешней функции.

Что такое свойство замыкания?

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

const myFunction = () => {
     let myValue = 2;
     console.log(myValue);
     const childFunction = () => {
          console.log(myValue += 1);
     }
     return childFunction;
}
const result = myFunction();
console.log(result);
result();
result();
result();

//Output
/* 
2
ƒ childFunction() {
     console.log(myValue += 1);
}
3
4
5 
*/

В этом примере myFunction, который создает новую функцию с именем childFunction. childFunction имеет доступ к переменным и функциям внутри myFunction даже после завершения выполнения myFunction. Это связано с тем, что childFunction формирует замыкание над областью действия myFunction, позволяя ему "запоминать" значение myValue между вызовами.

При вызове myFunction она записывает в консоль значение myValue, равное 2. Функция myFunction возвращает childFunction, и оно присваивается переменной result. Когда result регистрируется в консоли, она выводит определение функции childFunction. Затем он возвращает childFunction в переменную result. result теперь содержит ссылку на childFunction.

Когда result() вызывается три раза, в журнал записывается значение myValue плюс один, потому что childFunction увеличивает myValue при каждом вызове. Это происходит потому, что childFunction все еще может получить доступ к myValue через замыкание, даже если myFunction завершил выполнение.

Лучшие практики использования лексической области видимости и закрытия в JavaScript

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

  1. Избегайте создания ненужных замыканий: создание замыканий может потребовать большого объема памяти, поэтому важно создавать их только при необходимости.
  2. Используйте описательные имена переменных. Используйте описательные имена переменных, чтобы было понятно, что хранит замыкание и для чего оно используется.
  3. Избегайте прямого изменения переменных замыкания: прямое изменение переменных замыкания может привести к неожиданному поведению. Вместо этого используйте функции для контролируемого изменения переменных.
  4. Избегайте циклических ссылок. Создание циклических ссылок между замыканиями может привести к утечкам памяти, поэтому важно их избегать.