и один практический пример из реальной жизни
Что такое закрытия JavaScript?
Это функция JavaScript, которая позволяет функции получать доступ к ее внешней области действия. Звучит сложно?
Мы можем использовать эту функцию, когда у нас есть такие вложенные функции:
Как видите, функция sayAge
имеет доступ к переменной age
, которая находится во внешней области действия функции. Это особенность JavaScript, и мы можем использовать ее в некоторых ситуациях, которые я объясню.
Распространенный трюк с закрытием
Если мы возвращаем функцию из другой, мы можем изменить внешние переменные функции, используя функцию закрытия. Например:
Замыкания JavaScript так же просты, как этот пример, но я не понимал их, пока не нашел практического применения.
Реализация частных переменных с помощью замыканий JavaScript
Мы можем использовать эту функцию для реализации частных методов внутри функции JavaScript:
Как мы видим, setAge
имеет доступ к privateAge
и может изменять эту переменную. Мы вернули три метода: increment
, decrement
и value
, и пользователь не может назначить что-либо напрямую privateAge
.
Практический пример из реальной жизни
В этом примере я использовал несколько вещей, но, пожалуйста, не слишком увязните. Этот пример представляет собой простое экспресс-приложение на машинописном тексте, которое будет подключаться к базе данных (MongoDB) и выполнять запрос.
Если вы хотите использовать этот пример на своем локальном компьютере, выполните следующие действия:
- Вам нужен сервер MongoDB (порт по умолчанию в этом проекте установлен на 27022).
- Выполните эти команды:
git clone https://github.com/pshaddel/js-closure-example.git cd js-closure-example npm install npm run dev
У нас есть два маршрута: один для тестирования /ping
, который в ответ возвращает pong
, а другой - users
.
В этом примере для простоты я не использовал никаких сервисов или контроллеров. Посмотрим, что внутри users.ts
и connection.ts
:
На каждый get
запрос к /users
мы хотим выполнять find
запрос в базе данных MongoDB. Теперь общая проблема заключается в том, что мы не хотим создавать новое соединение для каждого запроса. Мы хотим использовать один экземпляр соединения, и есть два способа (по крайней мере, я знаю два способа: )). один из них использует шаблон и классы Singleton в машинописном тексте, а другой - Закрытие JavaScript.
Теперь давайте посмотрим на реализацию соединения, которое возвращает функцию с именем getDBClient
:
getDBClient
- это функция внутри этого файла, которая имеет доступ к внешней области функции. Итак, getDBClient
имеет доступ к databaseClient
переменной. Посмотрите на строку 9: если переменная databaseClient
не равна нулю, мы собираемся вернуть экземпляр client
, в противном случае мы собираемся создать нового клиента. Мы использовали закрытие, чтобы изменить внешнюю функциональную переменную.
Теперь, сколько бы раз мы ни вызывали этот API, код не будет создавать новое соединение с базой данных.
Используйте эту команду для отправки запроса, если вы используете Linux или Mac OS:
curl http://localhost:3000/users
Как мы можем видеть в первый раз, когда мы создали соединение с базой данных: Connected — Client Created
, и после этого каждый раз, когда нам требовалось соединение, код возвращал предыдущий экземпляр клиента базы данных и журналы: using previous instance
(connection.ts).