Прежде чем углубляться в замыкания в 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 есть несколько рекомендаций, которым следует следовать, чтобы убедиться, что ваш код ремонтопригоден и не содержит ошибок.
- Избегайте создания ненужных замыканий: создание замыканий может потребовать большого объема памяти, поэтому важно создавать их только при необходимости.
- Используйте описательные имена переменных. Используйте описательные имена переменных, чтобы было понятно, что хранит замыкание и для чего оно используется.
- Избегайте прямого изменения переменных замыкания: прямое изменение переменных замыкания может привести к неожиданному поведению. Вместо этого используйте функции для контролируемого изменения переменных.
- Избегайте циклических ссылок. Создание циклических ссылок между замыканиями может привести к утечкам памяти, поэтому важно их избегать.