0Pricing
JavaScript Academy · Урок

Как замыкания захватывают состояние

Разберитесь в лексическом окружении замыканий.

«Как замыкания захватывают состояние» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Как замыкания захватывают состояние
  2. Приватные переменные с замыканиями
  3. Модульный шаблон (IIFE)
  4. Функции-фабрики
← Назад к JavaScript Academy