[Hard] 📄 Closure
1. Что такое Closure?
Что такое замыкание (closure)?
Чтобы понять замыкания, сначала нужно разобраться в области видимости переменных в JavaScript и в том, как функция получает доступ к внешним переменным.
Область видимости переменных (Variable Scope)
В JavaScript область видимости обычно обсуждается как глобальная и функциональная (а также блочная с let/const).
// глобальная область видимости
let a = 1;
function parentFunction() {
// область видимости функции
let b = 2;
function childFunction() {
let c = 3;
console.log(a, b, c); // выводит 1 2 3, доступ к глобальной и внешней области
}
childFunction();
}
parentFunction();
console.log(a); // выводит 1, доступ к глобальной области
console.log(b, c); // ошибка: нет доступа к переменным внутри функции
Пример замыкания (Closure Example)
Замыкание формируется, когда дочерняя функция определяется внутри родительской и возвращается, сохраняя доступ к лексическому окружению родителя (что предотвращает немедленную сборку мусора для захваченных переменных).
function parentFunction() {
let count = 0;
return function childFunction() {
count += 1;
console.log(`Текущий счётчик: ${count}`);
};
}
const counter = parentFunction();
counter(); // выводит Текущий счётчик: 1
counter(); // выводит Текущий счётчик: 2
// `count` сохраняется, потому что childFunction всё ещё существует и хранит ссылку
Будьте осторожны: замыкания удерживают переменные в памяти. Чрезмерное использование может увеличить потребление памяти и снизить производительность.
2. Создайте функцию, удовлетворяющую следующим условиям
Создайте функцию (с использованием концепции замыканий), которая удовлетворяет:
plus(2, 5); // вывод 7
plus(2)(5); // вывод 7
Первое решение: две функции
Разделение на два стиля функций:
function plus(value, subValue) {
return value + subValue;
}
console.log(plus(2, 5));
// используем замыкание для сохранения value
function plus(value) {
return function (subValue) {
return value + subValue;
};
}
console.log(plus(2)(5));
Второе решение: одна функция
Первый подход может быть отклонён на собеседовании, если просят одну функцию для обоих стилей вызова.
function plus(value, subValue) {
// определяем поведение по количеству аргументов
if (arguments.length > 1) {
return value + subValue;
} else {
return function (item) {
return value + item;
};
}
}
console.log(plus(2, 5));
console.log(plus(2)(5));