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

Как забивается память?

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

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

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

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

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

Утечка памяти (memory leak) — это ситуация, когда приложение продолжает удерживать данные в памяти даже после того, как они больше не нужны. В JavaScript это может быть критичной проблемой, особенно в Single Page Applications (SPA), которые работают длительное время без перезагрузки.

Основные причины утечек памяти

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

2. Циклические ссылки Когда объект A ссылается на объект B, а объект B ссылается обратно на A, они могут остаться в памяти, если на них всё ещё есть ссылки сверху.

3. Closure и глобальные переменные Если функция захватывает большие переменные в closure, они остаются в памяти столько же, сколько живёт функция.

4. Забытые таймеры и интервалы setInterval и setTimeout создают ссылки, которые нужно очищать через clearInterval и clearTimeout.

5. Кэш без ограничений Неограниченный кэш может постоянно расти и занимать всё больше памяти.

6. Большие объекты в DOM элементах Если привязать большие объекты как properties DOM элементов, они останутся в памяти даже после удаления элемента из DOM.

Примеры и решения

// ПЛОХО: Утечка через обработчик события
function setupButton() {
  const button = document.getElementById("myButton");
  const largeData = new Array(1000000); // Большой объект
  
  button.addEventListener("click", () => {
    console.log(largeData); // Closure захватывает largeData
  });
  // largeData остаётся в памяти, даже если button удален из DOM
}

// ХОРОШО: Удаление обработчика
function setupButtonProperly() {
  const button = document.getElementById("myButton");
  
  function handleClick() {
    console.log("Clicked!");
  }
  
  button.addEventListener("click", handleClick);
  
  // Когда нужно удалить:
  button.removeEventListener("click", handleClick);
}

// ПЛОХО: Забытый интервал
function startPolling() {
  setInterval(() => {
    fetchData();
  }, 1000);
  // Интервал продолжит работать даже после того, как компонент удалён
}

// ХОРОШО: Контролируемый интервал
function startPollingProperly() {
  const intervalId = setInterval(() => {
    fetchData();
  }, 1000);
  
  return () => {
    clearInterval(intervalId); // Возвращаем функцию очистки
  };
}

// ПЛОХО: Неограниченный кэш
const cache = {};
function cacheResult(key, value) {
  cache[key] = value; // Кэш только растёт
}

// ХОРОШО: Кэш с ограничением
const createLRUCache = (maxSize) => {
  const cache = new Map();
  
  return {
    set(key, value) {
      if (cache.size >= maxSize) {
        const firstKey = cache.keys().next().value;
        cache.delete(firstKey);
      }
      cache.set(key, value);
    },
    get(key) {
      return cache.get(key);
    }
  };
};

// ПЛОХО: Большие объекты в DOM
const user = { id: 1, name: "John", largeData: new Array(1000000) };
element.userData = user; // Объект привязан к DOM элементу

// ХОРОШО: Использование WeakMap
const userDataMap = new WeakMap();
userDataMap.set(element, user); // Если element удалится, данные тоже

// ПЛОХО: Циклические ссылки
function Parent() {
  this.child = new Child(this); // child ссылается на parent
}
function Child(parent) {
  this.parent = parent; // parent ссылается на child
}

// ХОРОШО: Использование WeakMap для ссылки на parent
function ParentFixed() {
  this.child = new ChildFixed();
  parentMap.set(this.child, this);
}
function ChildFixed() {}
const parentMap = new WeakMap();

Инструменты для поиска утечек

В браузере можно использовать Chrome DevTools:

  • Memory вкладка для снимков памяти (Heap Snapshots)
  • Performance вкладка для отслеживания использования памяти во времени
  • Console для запуска performance.memory в Firefox и Chrome

Заключение

Утечки памяти в JavaScript — это частая проблема в долгоживущих приложениях. Основное правило: всегда удаляйте то, что вы добавили (обработчики событий, таймеры), используйте WeakMap/WeakSet для циклических ссылок и ограничивайте размер кэшей.

Как забивается память? | PrepBro