Що таке замикання (Closures) в JavaScript?
Замикання (Closure) - це комбінація функції та лексичного оточення, в якому ця функція була оголошена. Замикання дає доступ до області видимості зовнішньої функції з внутрішньої функції.
Основні поняття
Як працюють замикання
function outerFunction(x) {
// Зовнішня змінна
function innerFunction(y) {
// Внутрішня функція має доступ до змінної x
console.log(x + y);
}
return innerFunction;
}
const myFunction = outerFunction(10);
myFunction(5); // Виведе 15
Приклад із лічильником
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
Практичні застосування
1. Інкапсуляція даних
function createBankAccount(initialBalance) {
let balance = initialBalance;
return {
deposit: function(amount) {
balance += amount;
return balance;
},
withdraw: function(amount) {
if (amount <= balance) {
balance -= amount;
return balance;
}
return 'Insufficient funds';
},
getBalance: function() {
return balance;
}
};
}
const account = createBankAccount(100);
console.log(account.deposit(50)); // 150
console.log(account.withdraw(30)); // 120
console.log(account.getBalance()); // 120
2. Фабрика функцій
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
3. Модульний патерн
const myModule = (function() {
let privateVariable = 0;
function privateFunction() {
console.log('Приватна функція');
}
return {
publicMethod: function() {
privateVariable++;
privateFunction();
return privateVariable;
},
getPrivateVariable: function() {
return privateVariable;
}
};
})();
myModule.publicMethod(); // "Приватна функція", повертає 1
Поширені пастки
Проблема з циклами
// Неправильно
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // Виведе 3, 3, 3
}, 100);
}
// Правильно з замиканням
for (var i = 0; i < 3; i++) {
(function(index) {
setTimeout(function() {
console.log(index); // Виведе 0, 1, 2
}, 100);
})(i);
}
// Або з let
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // Виведе 0, 1, 2
}, 100);
}
Переваги та недоліки
Переваги:
- Інкапсуляція даних
- Створення приватних змінних
- Фабрика функцій
Недоліки:
- Можливі витоки пам'яті
- Складність для розуміння новачками
- Додаткове споживання пам'яті
Замикання - потужний інструмент JavaScript, який дозволяє створювати елегантні та безпечні рішення.