PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • Подписка
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • PurpleFlow
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюсPurpleMax
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • Подписка
    • AI для кодаНовое
    • Сообщество
    Главная
    Сообщество
    Замыкания в JavaScript: полное руководство с примерами

    Замыкания в JavaScript: полное руководство с примерами

    Аватар автора Замыкания в JavaScript: полное руководство с примерами

    Антон Ларичев

    Иконка календаря25 июня 2026
    JavaScriptзамыканияосновы JSфункцииscopejuniorИконка уровня junior
    Картинка поста Замыкания в JavaScript: полное руководство с примерами

    Введение

    Замыкания — одна из тех концепций JavaScript, которая пугает новичков, но становится незаменимым инструментом в руках опытного разработчика. В этой статье разберём, что такое замыкание, как оно работает «под капотом» и когда его использовать на практике.

    Что такое замыкание

    Замыкание (closure) — это функция, которая «помнит» переменные из своей внешней области видимости даже после того, как внешняя функция завершила выполнение.

    Звучит сложно? Давайте на примере:

    function создатьСчётчик() {
      // переменная живёт во внешней области видимости
      let счёт = 0;
    
      return function() {
        счёт += 1;
        return счёт;
      };
    }
    
    const счётчик = создатьСчётчик();
    console.log(счётчик()); // 1
    console.log(счётчик()); // 2
    console.log(счётчик()); // 3

    Функция, которую возвращает создатьСчётчик, «захватывает» переменную счёт. Каждый вызов увеличивает её значение, и оно сохраняется между вызовами — хотя создатьСчётчик давно отработала.

    Как работает область видимости

    Чтобы понять замыкания, нужно разобраться с областями видимости (scope).

    В JavaScript каждая функция создаёт свою область видимости. Переменные, объявленные внутри функции, недоступны снаружи. Но вложенная функция видит переменные родительской:

    function внешняя() {
      const сообщение = 'Привет';
    
      function внутренняя() {
        // внутренняя видит переменные родителя
        console.log(сообщение);
      }
    
      внутренняя();
    }
    
    внешняя(); // Привет

    Цепочка областей видимости называется scope chain. Когда JavaScript ищет переменную, он проверяет текущую область, затем родительскую, и так вплоть до глобальной. Замыкание — это сохранение этой цепочки после выхода из функции.

    Замыкание на практике

    Инкапсуляция данных

    Замыкания позволяют скрыть данные от внешнего мира — аналог приватных полей класса:

    function создатьКошелёк(начальныйБаланс) {
      let баланс = начальныйБаланс;
    
      return {
        пополнить(сумма) {
          баланс += сумма;
          console.log(`Баланс: ${баланс}`);
        },
        снять(сумма) {
          if (сумма > баланс) {
            console.log('Недостаточно средств');
            return;
          }
          баланс -= сумма;
          console.log(`Баланс: ${баланс}`);
        },
        проверить() {
          return баланс;
        }
      };
    }
    
    const кошелёк = создатьКошелёк(1000);
    кошелёк.пополнить(500); // Баланс: 1500
    кошелёк.снять(200);     // Баланс: 1300
    // прямого доступа к переменной баланс нет — только через методы

    Функции-фабрики

    Замыкания удобны для создания похожих функций с разными начальными параметрами:

    function создатьМножитель(множитель) {
      // множитель захватывается в замыкание
      return function(число) {
        return число * множитель;
      };
    }
    
    const удвоить = создатьМножитель(2);
    const утроить = создатьМножитель(3);
    
    console.log(удвоить(5));  // 10
    console.log(утроить(5)); // 15

    Мемоизация

    Замыкание может хранить кэш результатов дорогостоящих вычислений:

    function мемоизировать(fn) {
      const кэш = {}; // кэш живёт в замыкании
    
      return function(аргумент) {
        if (кэш[аргумент] !== undefined) {
          console.log('Из кэша');
          return кэш[аргумент];
        }
        кэш[аргумент] = fn(аргумент);
        return кэш[аргумент];
      };
    }
    
    const кешированноеВозведение = мемоизировать((n) => n * n);
    
    console.log(кешированноеВозведение(4)); // 16
    console.log(кешированноеВозведение(4)); // Из кэша → 16

    Частые ошибки

    Замыкание в цикле с var

    Классическая ловушка для новичков:

    // Неправильно: все функции захватывают одну и ту же переменную i
    for (var i = 0; i < 3; i++) {
      setTimeout(function() {
        console.log(i); // выведет 3, 3, 3
      }, 1000);
    }
    
    // Правильно: let создаёт новую переменную для каждой итерации
    for (let i = 0; i < 3; i++) {
      setTimeout(function() {
        console.log(i); // выведет 0, 1, 2
      }, 1000);
    }

    Проблема с var в том, что он не создаёт новую переменную на каждой итерации — все колбэки ссылаются на одну i. К моменту срабатывания таймаута цикл завершился, и i равно 3. let решает проблему, создавая отдельный экземпляр для каждой итерации.

    Утечки памяти

    Замыкания удерживают в памяти всю цепочку областей видимости. Если замыкание живёт долго, а родительская область содержит тяжёлые данные — это утечка:

    function проблемнаяФункция() {
      // тяжёлые данные в родительской области
      const большойМассив = new Array(1000000).fill('данные');
    
      return function() {
        // замыкание удерживает большойМассив в памяти, хотя не использует
        return 'Привет';
      };
    }
    
    const утечка = проблемнаяФункция();
    // большойМассив не будет очищен сборщиком мусора

    Решение: не объявляйте тяжёлые данные там, где они не нужны замыканию, или обнуляйте переменную явно после использования.

    Неожиданное разделение состояния

    function создатьПриветствие(имя) {
      let сообщение = `Привет, ${имя}!`;
    
      return {
        показать() {
          console.log(сообщение);
        },
        изменить(новоеИмя) {
          // все методы разделяют одну захваченную переменную
          сообщение = `Привет, ${новоеИмя}!`;
        }
      };
    }
    
    const привет = создатьПриветствие('Иван');
    привет.показать();         // Привет, Иван!
    привет.изменить('Мария');
    привет.показать();         // Привет, Мария!

    Это не всегда ошибка, но важно помнить: все методы объекта, созданного через замыкание, разделяют одно и то же захваченное состояние.

    Заключение

    Замыкания — фундаментальная концепция JavaScript, которая лежит в основе множества паттернов: модульного кода, каррирования, мемоизации и реактивного программирования. Понимание того, как функции захватывают переменные из внешних областей видимости, открывает доступ к более чистому и выразительному коду.

    Главное запомнить: замыкание — это не магия. Это функция, которая помнит среду, в которой была создана. Начните применять их в небольших задачах — счётчики, фабрики, кэширование — и вы быстро почувствуете их силу.

    Иконка глаза618

    Комментарии

    0
    Бесплатный курс

    Учитесь программировать с AI-агентом — бесплатно

    Курс «AI в обучении: OpenCode и skills»: поставите агента и разберёте с ним любую тему — как эту статью.

    opencode

    >объясни этот код и дай задачу

    ◆Читаю src/server.ts…

    ✓Разбор готов: 4 шага

    ✓Задача → practice/01.md

    • Установка и настройка OpenCode
    • Агент и skills на практике
    • 13 уроков, 3 модуля
    Начать бесплатно

    0 ₽ · доступ сразу после регистрации

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Продвинутый JavaScript

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    TypeScript с нуля

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Neovim

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Верификация Claude из России: что это и почему не проходит
    Иконка аватараАнтон
    Иконка календаря07 ноября 2026
    AnthropicAI-инструментыClaude CodejuniorИконка уровня junior

    Верификация Claude из России: что это и почему не проходит

    Что такое верификация Claude через Persona, какие документы нужны, почему она не проходит и что делать из России без чужих документов и номеров.

    Иконка чипа0
    Иконка глаза42
    Иконка комментариев0
    Картинка поста Как установить OpenCode на Windows
    Иконка аватараАнтон
    Иконка календаря06 ноября 2026
    AI-инструментыapiразработкаjuniorИконка уровня junior

    Как установить OpenCode на Windows

    Как установить OpenCode на Windows через npm, Chocolatey, Scoop или WSL, задать ключ в PowerShell, подключить модель из России и исправить частые ошибки.

    Иконка чипа0
    Иконка глаза1 566
    Иконка комментариев0
    Картинка поста Claude не работает или не открывается: причины и решения
    Иконка аватараАнтон
    Иконка календаря05 ноября 2026
    AnthropicAI-инструментыClaude CodejuniorИконка уровня junior

    Claude не работает или не открывается: причины и решения

    Почему Claude не работает или не открывается: сбой Anthropic, регион, сеть, аккаунт или лимит. Как найти причину по симптому и что делать из России.

    Иконка чипа0
    Иконка глаза2 121
    Иконка комментариев0
    Иконка чипа0