Замыкания

Модуль 1: Web Core
19 уровень , 5 лекция
Открыта

6.1 Понятие замыканий

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

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

Основные свойства замыканий:

  1. Лексическое окружение: контекст, в котором была объявлена функция, включая все переменные, доступные на момент объявления.
  2. Сохранение контекста: функция с замыканием может сохранить доступ к переменным из внешней области видимости даже после завершения выполнения этой внешней функции.

6.2 Примеры работы замыканий

Пример 1: Простое замыкание

В этом примере innerFunction() имеет доступ к переменной outerVariable из своей внешней области видимости даже после завершения выполнения outerFunction().

JavaScript
    
      function outerFunction() {
        let outerVariable = 'I am from the outer function';

        function innerFunction() {
          console.log(outerVariable);
        }
        return innerFunction;
      }

      const closure = outerFunction();
      closure(); // Выведет: I am from the outer function
    
  

Пример 2: Счетчик с использованием замыкания

В этом примере функция-счетчик сохраняет значение переменной count и увеличивает его при каждом вызове.

JavaScript
    
      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
    
  

Пример 3: Замыкание в цикле

Замыкания часто используются для сохранения значений переменных в циклах.

В этом примере каждая функция внутри массива arr "запоминает" значение переменной i в момент своего создания благодаря блочной области видимости let:

JavaScript
    
      function createArrayWithClosures() {
        let arr = [];

        for (let i = 0; i < 3; i++) {
          arr[i] = function() {
            console.log(i);
          };
        }
        return arr;
      }

      const closures = createArrayWithClosures();

      closures[0](); // Выведет: 0
      closures[1](); // Выведет: 1
      closures[2](); // Выведет: 2
    
  

6.3 Сложные сценарии использования замыканий

Пример 1: Частичное применение функции (partial application)

Замыкания позволяют создавать частично примененные функции, сохраняя некоторые аргументы фиксированными.

В этом примере функция multiply() возвращает функцию, которая умножает переданный ей аргумент b на зафиксированный аргумент a.

JavaScript
    
      function multiply(a) {
        return function(b) {
          return a * b;
        };
      }

      const double = multiply(2);
      console.log(double(5)); // Выведет: 10
      console.log(double(10)); // Выведет: 20
    
  

Пример 2: Скрытие данных (data hiding)

Замыкания могут использоваться для создания приватных переменных и методов.

В этом примере переменные _name и _age являются приватными и доступны только через методы объекта:

JavaScript
    
      function createPerson(name, age) {
        let _name = name;
        let _age = age;

        return {
          getName: function() {
            return _name;
          },
          getAge: function() {
            return _age;
          },
          setName: function(newName) {
            _name = newName;
          },
          setAge: function(newAge) {
            _age = newAge;
          }
        };
      }

      const person = createPerson('John', 30);
      console.log(person.getName()); // Выведет: John

      person.setName('Jane');

      console.log(person.getName()); // Выведет: Jane
      console.log(person.getAge());  // Выведет: 30
    
  

Пример 3: Мемоизация

Мемоизация — это техника оптимизации, при которой результаты функции сохраняются, чтобы избежать повторных вычислений для одинаковых входных данных.

В этом примере функция memoize() использует замыкание для сохранения кеша вычисленных результатов функции fn():

JavaScript
    
      function memoize(fn) {
        const cache = {};

        return function(...args) {
          const key = JSON.stringify(args);
          if (cache[key]) {
            return cache[key];
          }
          const result = fn(...args);
          cache[key] = result;
          return result;
        };
      }

      function slowFunction(num) {
        console.log('Computing...');
        return num * 2;
      }

      const memoizedFunction = memoize(slowFunction);

      console.log(memoizedFunction(5)); // Выведет: Computing... 10
      console.log(memoizedFunction(5)); // Выведет: 10 (результат взят из кеша)
    
  
1
Задача
Модуль 1: Web Core, 19 уровень, 5 лекция
Недоступна
Счётчик с замыканием
Счётчик с замыканием
1
Задача
Модуль 1: Web Core, 19 уровень, 5 лекция
Недоступна
Приватные переменные
Приватные переменные
1
Опрос
Date, Timer и литералы, 19 уровень, 5 лекция
Недоступен
Date, Timer и литералы
Date, Timer и литералы
Комментарии (3)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Gans Electro Уровень 40
1 ноября 2025
Все же в JS много вещей которые в Java нет. И они довольно необычны, сложно разобраться сходу, хотя примерно понял что к чему и что значит "динамический язык".
Vadim Makarenko Уровень 42
12 августа 2025
У меня вызвал сложности разбор Примера 3: замыкания в цикле. Для тех, кто хочет твёрже закрепить эту тему: https://learn.javascript.ru/closure В самом конце разбирается и этот пример. По поводу Примера 1 из пункта 6.3. Из того же источника узнал, что этот же код приводится на собеседованиях, когда необходимо создать функцию перемножения с вызовом multiply(a)(b) (конечно ничего фиксировать в этом случае не требуется).
Ilona Уровень 23
15 апреля 2025
Если вы даете примеры с геттерами и сеттерами, у меня вопрос: почему до этого вы ни разу не обьясняли что это такое и для чего они используются? + опять в задачах копипаста из примеров