Узнайте все о замыканиях и о том, как использовать их в своем собственном коде
JavaScript - это универсальный язык программирования, который допускает широкий спектр методов кодирования, включая одну из самых неправильно понимаемых функций из всех: замыкания.
Замыкания - это мощная функция JavaScript, которую можно использовать для создания приватных переменных, реализации области видимости на уровне функций и обеспечения чистого и эффективного способа создания повторно используемого кода.
В этой статье о JavaScript 101 мы более подробно рассмотрим замыкания и рассмотрим некоторые практические варианты использования.
Что такое замыкания в JavaScript?
Всякий раз, когда вы определяете функцию в JavaScript, среда выполнения как бы делает снимок функции и всего ее окружения. Это включает в себя саму функцию, да, но также переменные из области видимости, в которой была определена функция.
Позвольте объяснить:
functionwrapper() {
let a =" 1;
let b =" "hello!";
returnfunctioninsideFunction() {
console.log("accessing outside variables: ", a, "-", b);
}
}
Видите этот код? Когда вы определяете insideFunction
, сделанный снимок охватывает саму функцию, а также добавляет переменные a
и b
.
Другими словами, в JavaScript замыкание создается, когда внутренняя функция имеет доступ к переменным и параметрам внешней функции.
Это означает, что внутренняя функция “закрывается” над внешней функцией, создавая область видимости, которая включает в себя как внутреннюю, так и внешние функции. Это может быть невероятно полезно для создания приватных переменных, реализации области видимости на уровне функций и создания повторно используемого кода (подробнее об этом мы поговорим через секунду).
Создание приватных переменных с помощью замыканий
Одним из наиболее практичных применений замыканий является создание приватных переменных. Приватные переменные - это переменные, которые доступны только в контексте конкретной функции или объекта и к которым нельзя получить доступ или изменить вне этого контекста.
Конечно, классы в JavaScript уже предоставляют возможность объявлять частные свойства, но если вы собираетесь работать в полную силу, то приватные переменные - это не вариант, если, конечно, вы не используете замыкания.
Это может быть полезно для защиты конфиденциальных данных или для создания более безопасного и простого в обслуживании инкапсулированного кода.
Вот пример использования замыканий для создания приватных переменных в JavaScript:
functioncreateCounter() {
let count =" 0;
returnfunction() {
count++;
console.log(count);
}
}
let counter =" createCounter();
counter(); // Output: 1
counter(); // Output: 2
В этом примере createCounter
- это функция, которая создает новое замыкание каждый раз, когда она вызывается (потому что она определяет, а затем возвращает новую функцию). Каждое замыкание имеет доступ к своей собственной count
переменной, которая доступна только изнутри замыкания. При counter
вызове он увеличивает закрытую count
переменную и записывает ее значение в консоль.
Другими словами, мы создали новую закрытую переменную: count
Обработчики событий
Еще один очень практичный вариант использования замыканий - это написание собственных обработчиков.
Рассмотрим сценарий, в котором вы хотите добавить прослушиватели событий к нескольким элементам веб-страницы. Один из способов сделать это - добавить отдельный прослушиватель событий к каждому элементу, вот так:
var buttons =" document.querySelectorAll('button');
for (var i =" 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
console.log('Button ' + i + ' clicked');
});
}
В этом примере мы выбираем все button
элементы на странице и добавляем прослушиватель событий щелчка к каждому из них.
Однако, когда запускается событие click, для всех прослушивателей событий используется одна и та же переменная i
, что означает, что результатом всегда будет "Нажата кнопка n", где n
это значение buttons.length
, потому что i
оно всегда будет buttons.length
таким ко времени запуска события click.
Чтобы решить эту проблему, мы можем использовать замыкания для инкапсуляции значения i
в каждом прослушивателе событий:
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', (function(index) {
return function() {
console.log('Button ' + index + ' clicked');
}
})(i));
}
В этом примере мы оборачиваем функцию прослушивания событий в другую функцию, которая принимает i
в качестве аргумента и возвращает функцию прослушивания событий. Возвращаемая функция представляет собой замыкание, которое имеет доступ к значению index
, переданному в качестве аргумента, которое является значением i
во время создания замыкания.
При использовании замыканий каждый прослушиватель событий имеет свою собственную index
переменную, которая отличается для каждого прослушивателя событий, и результатом будет "Кнопка n нажата", где n
это индекс кнопки, на которую было нажато.
Создание повторно используемого кода
Замыкания также можно использовать для создания повторно используемого кода, который можно передавать по кругу и использовать в разных контекстах. Это особенно полезно, когда у вас есть функция, которая принимает обратный вызов в качестве аргумента, но вы хотите передать дополнительные аргументы обратному вызову без изменения исходной сигнатуры функции.
Вот пример использования замыканий для создания повторно используемой функции обратного вызова:
functioncreateCallback(arg1, arg2) {
returnfunction(result) {
console.log(arg1 + ' ' + arg2 + ' =" ' + "result);
}
}
const callback1 =" createCallback('5', '6');
const callback2 =" createCallback('10', '20');
callback1(11); // Output: 5 6 =" 11
callback2(30); // Output: 10 20 = 30
В этом примере createCallback
это функция, которая возвращает новое замыкание каждый раз, когда она вызывается. Замыкание принимает один аргумент, result
и регистрирует строку, которая объединяет arg1
, arg2
и result
.
Это создает повторно используемую функцию обратного вызова, которая может передаваться различным функциям и использоваться в разных контекстах.
Замыкания - это мощная функция JavaScript, которую можно использовать для создания закрытых переменных, реализации четных обработчиков и создания повторно используемого кода. Понимая, как работают замыкания и как их эффективно использовать, вы можете написать более безопасный, обслуживаемый и эффективный код.
Конечно, это непростая концепция, и к ней может потребоваться некоторое привыкание, но как только вы освоите ее, уровень вашей игры на JavaScript повысится!
Итак, дерзайте и начните использовать замыкания в своем коде JavaScript уже сегодня!