Как замыкания захватывают состояние
Разберитесь в лексическом окружении замыканий.
«Как замыкания захватывают состояние» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.
Что такое замыкание
Замыкание — это функция, объединённая со ссылками на переменные из области видимости, в которой она была определена. Внутренняя функция «запоминает» эти переменные даже после возврата из внешней функции.
function outer() {
const message = "hello";
function inner() {
console.log(message); // sees outer variable
}
inner();
}
outer(); // "hello"Возврат внутренней функции
Всё самое интересное происходит при возврате внутренней функции. Она сохраняет доступ к внешней переменной, хотя outer уже завершила работу.
function outer() {
const message = "remembered";
return function () {
console.log(message);
};
}
const fn = outer();
fn(); // "remembered"Лексическая область видимости
Замыкания работают благодаря лексической области видимости: функция может обращаться к переменным, определённым в областях видимости, которые физически окружают её в исходном коде, а не в месте её вызова.
const x = 10;
function show() {
console.log(x); // resolves where defined
}
function run() {
const x = 99;
show(); // still logs 10, not 99
}
run();Захват по ссылке
Замыкание захватывает саму переменную, а не снимок её значения. Если переменная позже изменится, замыкание увидит новое значение.
function make() {
let count = 0;
const get = () => count;
count = 5; // changed after get defined
return get;
}
console.log(make()()); // 5Каждый вызов создаёт новую область видимости
Каждый вызов внешней функции создаёт новый набор переменных. Замыкания, созданные разными вызовами, не разделяют состояние.
function counter() {
let n = 0;
return () => ++n;
}
const a = counter();
const b = counter();
console.log(a(), a()); // 1 2
console.log(b()); // 1 (independent)Замыкания над параметрами
Параметры функций также захватываются. Это позволяет создавать специализированные функции на основе общей.
function adder(x) {
return (y) => x + y;
}
const add5 = adder(5);
console.log(add5(3)); // 8
console.log(add5(10)); // 15Классическая ловушка цикла
Известная ошибка: использование var в цикле приводит к тому, что все замыкания используют одну переменную. К моменту их выполнения цикл уже завершён, поэтому все они видят последнее значение.
const fns = [];
for (var i = 0; i < 3; i++) {
fns.push(() => i);
}
console.log(fns[0](), fns[1](), fns[2]()); // 3 3 3Исправление с помощью let
let создаёт новую привязку на каждой итерации, поэтому каждое замыкание захватывает собственную переменную i. Это современное решение проблемы.
const fns = [];
for (let i = 0; i < 3; i++) {
fns.push(() => i);
}
console.log(fns[0](), fns[1](), fns[2]()); // 0 1 2Замыкания сохраняют память
Пока существует замыкание, захваченные им переменные не могут быть удалены сборщиком мусора. Обычно это не проблема, но может привести к утечкам, если хранить замыкания дольше необходимого.
function make() {
const big = new Array(3).fill("data");
return () => big.length;
}
const f = make();
console.log(f()); // 3 - big stays in memory via fЗамыкания повсюду
Обратные вызовы, обработчики событий, setTimeout, методы массивов и промисы используют замыкания для сохранения контекста. Вы постоянно применяете их, часто даже не замечая этого.
function greet(name) {
return () => console.log("Hi " + name);
}
[greet("Ada"), greet("Bob")].forEach((fn) => fn());
// Hi Ada
// Hi BobИзучение захваченного состояния
Несколько замыканий, созданных в рамках одного вызова, используют одни и те же захваченные переменные, поэтому одно замыкание может прочитать то, что записало другое.
function pair() {
let value = 0;
return {
set: (v) => { value = v; },
get: () => value
};
}
const p = pair();
p.set(42);
console.log(p.get()); // 42Быстрая проверка
Как замыкания захватывают состояние.
Повторение
Замыкание — это функция вместе со ссылками на область видимости, в которой она определена. Благодаря лексической области видимости оно помнит внешние переменные после возврата внешней функции, захватывая их по ссылке, а не по значению. Каждый вызов внешней функции создаёт независимую область видимости; используйте let, чтобы избежать ловушки цикла. Замыкания сохраняют захваченную память и лежат в основе обратных вызовов повсюду.
Часто задаваемые вопросы
Урок «Как замыкания захватывают состояние» бесплатный?
Да — полный текст урока «Как замыкания захватывают состояние» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Как замыкания захватывают состояние»?
Разберитесь в лексическом окружении замыканий. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать JavaScript Academy?
Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Как замыкания захватывают состояние»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке JavaScript Academy?
Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Как замыкания захватывают состояние
- Приватные переменные с замыканиями
- Модульный шаблон (IIFE)
- Функции-фабрики