Замыкания — популярная тема среди интервьюеров Javascript, и на то есть веские причины. Они являются ключевым аспектом языка, который позволяет создавать мощные библиотеки. В этом сообщении блога мы рассмотрим концепцию замыканий в Javascript.
Что такое Закрытие?
Javascript рассматривает функции как объекты, и эта уникальная характеристика позволяет функции возвращать объект или даже другую функцию. Эта возможность полезна при изменении поведения функции во время выполнения. Например:
function MathOperation(operation) { if(operation === 'add'){ return function(a, b){ return a + b; } }else if(operation === 'subtract'){ return function(a, b) { return x + y; }; } } console.log(MathOperation('add')(5,3)); // 8 console.log(MathOperation('subtract')(5,3)); //2
В приведенном выше примере функция MathOperation
возвращает функцию на основе переданного аргумента. Возвращенная функция затем может быть вызвана с аргументами для выполнения предполагаемой операции.
Родительская функция — MathOperation
, а внутренние функции — ее дочерние элементы. В некоторых сценариях дочерние функции используют значение, объявленное в родительской функции. В таких случаях дочерняя функция также несет в себе контекст выполнения своей родительской функции, даже если родительская функция уже исчезла.
Рассмотрим следующий пример с двумя анонимными функциями:
const add5 = function () { const x = 5; return function (y) { return x + y; }; }(); console.log(add5(3)); // 8 console.log(add5(4)); // 9 console.log(add5(15)); // 20
Здесь, когда вы объявляете const add5
, у него есть выражение немедленно вызываемой функции (IIFE). Это означает, что функция, объявленная рядом с add5, следует за фигурными скобками ()
, что гарантирует выполнение функции немедленно во время объявления. В связи с этим после объявления add5
содержит определение функции, показанное ниже.
const add5 = function(y){ return 5 + y; }
Обратите внимание, что здесь внутренняя функция несет контекст выполнения родительской функции в форме const x = 5;
Теперь, когда внешняя функция уже исчезла, нет другого способа изменить или получить доступ к значению x
, кроме как через функцию add5
. Эта техника называется замыканием.
Где я должен использовать замыкание?
Замыкания могут использоваться различными способами в реальном программировании на JavaScript. Некоторые распространенные варианты использования:
- Реализация закрытых переменных или методов. Вы можете использовать замыкание для создания закрытых переменных или методов, доступ к которым возможен только в пределах области замыкания.
function counter() { let count = 0; return function() { count++; return count; }; } const increment = counter(); console.log(increment()); // 1 console.log(increment()); // 2 console.log(increment()); // 3
2. Управление памятью. Замыкания могут использоваться для сохранения ссылки на переменную даже после того, как ее родительская функция завершила выполнение. Это может быть полезно для управления памятью и предотвращения нежелательной сборки мусора.
function person() { let name = "John Doe"; return { getName: function() { return name; }, setName: function(newName) { name = newName; } }; } const john = person(); console.log(john.getName()); // John Doe john.setName("Jane Doe"); console.log(john.getName()); // Jane Doe
3. Обратные вызовы. Замыкания могут использоваться для создания функций, которые можно передавать в качестве аргументов другим функциям и выполнять позже. Это распространенный вариант использования обратных вызовов.
function greeting(name) { return function(message) { console.log(`${message} ${name}`); }; } const sayHi = greeting("John"); sayHi("Hello"); // Hello John
4. Реализация шаблонов модулей. Замыкания могут использоваться для создания модулей с закрытыми переменными и методами, доступ к которым извне невозможен. Это может быть полезно при создании автономных блоков кода.
function multiply(a, b) { return a * b; } function partialMultiplyByFive(b) { return multiply(5, b); } console.log(partialMultiplyByFive(2)); // 10 console.log(partialMultiplyByFive(3)); // 15
5. Обработчики событий. Замыкания могут использоваться для сохранения ссылки на конкретное состояние переменной даже после того, как произошло событие. Это может быть полезно при работе с обработчиками событий.
function addEventHandler(num1, num2) { return function() { console.log(num1 + num2); }; } const btn = document.querySelector('button'); btn.addEventListener('click', addEventHandler(10, 20));
Заключение
Замыкания — это фундаментальная концепция в JavaScript, которая позволяет создавать функции с постоянным доступом к переменным в их родительских областях даже после того, как родительская функция завершила выполнение. Это открывает ряд возможностей для реализации частных переменных, управления памятью, обратных вызовов, шаблонов модулей и обработчиков событий, а также других вариантов использования. Понимание концепции замыканий имеет решающее значение для разработки надежных и эффективных приложений на JavaScript.