← Назад к вопросам

Как замыкание используется в JavaScript?

1.0 Junior🔥 61 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Замыкания в JavaScript

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

Как работает замыкание

function outer() {
  const message = "Hello from outer";
  
  function inner() {
    console.log(message); // inner имеет доступ к переменной outer
  }
  
  return inner;
}

const closure = outer();
closure(); // "Hello from outer"

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

Практические примеры

Приватные переменные

Замыкания позволяют создавать приватные переменные, которые недоступны извне:

function createCounter() {
  let count = 0; // Приватная переменная
  
  return {
    increment() {
      return ++count;
    },
    decrement() {
      return --count;
    },
    getCount() {
      return count;
    }
  };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
console.log(counter.getCount());  // 1

// count недоступна напрямую
console.log(counter.count); // undefined

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

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

function multiply(multiplier) {
  return function(number) {
    return number * multiplier;
  };
}

const double = multiply(2);
const triple = multiply(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

Обработчики событий

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

function setupButtons() {
  for (let i = 1; i <= 3; i++) {
    const button = document.createElement("button");
    button.textContent = `Button ${i}`;
    
    button.addEventListener("click", () => {
      console.log(`Button ${i} clicked`); // Замыкание сохраняет i
    });
    
    document.body.appendChild(button);
  }
}

setupButtons();

Декораторы и middleware

function withLogging(fn) {
  return function(...args) {
    console.log(`Calling ${fn.name} with args:`, args);
    const result = fn(...args);
    console.log(`Result:`, result);
    return result;
  };
}

const add = (a, b) => a + b;
const addWithLog = withLogging(add);

addWithLog(2, 3);
// "Calling add with args: [2, 3]"
// "Result: 5"

Кеширование результатов (Memoization)

function memoize(fn) {
  const cache = {}; // Замыкание сохраняет кеш
  
  return function(n) {
    if (n in cache) {
      console.log("From cache");
      return cache[n];
    }
    
    const result = fn(n);
    cache[n] = result;
    return result;
  };
}

const fibonacci = memoize((n) => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

console.log(fibonacci(10)); // Вычисляется
console.log(fibonacci(10)); // Из кеша

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

Проблема с циклом и var

// Неправильно
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 3, 3, 3 (i ссылается на последнее значение)
  }, 100);
}

// Правильно с let
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 0, 1, 2 (let создаёт новую область видимости)
  }, 100);
}

// Или с замыканием
for (var i = 0; i < 3; i++) {
  (function(j) {
    setTimeout(() => {
      console.log(j); // 0, 1, 2
    }, 100);
  })(i);
}

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

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

// Потенциально проблемный код
const hugeArray = new Array(1000000);
const getElement = () => hugeArray[0];

// getElement держит ссылку на весь hugeArray в памяти

Замыкания в React

У React-разработчиков замыкания — это постоянная работа с хуками:

function Counter() {
  const [count, setCount] = useState(0);
  
  const handleClick = () => {
    setCount(count + 1); // handleClick замыкается на count
  };
  
  useEffect(() => {
    const timer = setTimeout(() => {
      console.log(`Count: ${count}`); // Замыкание на текущий count
    }, 1000);
    
    return () => clearTimeout(timer);
  }, [count]); // count в зависимостях
  
  return <button onClick={handleClick}>Count: {count}</button>;
}

Заключение

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

Как замыкание используется в JavaScript? | PrepBro