JS Advanced

Сборка мусора (Garbage Collection)

Понять, как JavaScript определяет unreachable объекты и удаляет их, и почему GC timing недетерминирован.

Продвинутый (Advanced)

Кратко

Garbage Collection (GC) автоматически удаляет unreachable объекты. Объект unreachable, когда нет ни одной ссылки на него. Типичные memory leaks: забытые event listeners, глобальные переменные, замыкания, DOM-ссылки. GC timing недетерминирован — нельзя предсказать, когда GC сработает.


Подробно

Доступность (reachability):

// Доступен: let user = { name: 'Анна' }; // { name: 'Анна' } — reachable через user

// Недоступен: user = null; // { name: 'Анна' } — unreachable, GC удалит

Корневые объекты (root):

  • global object (window)
  • текущий call stack (локальные переменные)
  • DOM-дерево

Типичные memory leaks:

  • Забытый event listener:

function setup() { const button = document.querySelector('button'); button.addEventListener('click', () => { // closured переменные не удаляются }); } // Если button удалён из DOM — listener всё ещё существует!

  • Глобальные переменные:

function leak() { hugeData = new Array(1000000).fill('x'); // нет let/const! } // hugeData — в window, никогда не удалится

  • Замыкания:

function createLeak() { const big = new Array(1000000); return function() { // big недоступен, но замыкание может удерживать ссылку return 'done'; }; }

  • DOM-ссылки:

const elements = {}; function addItem(element) { elements[element.id] = element; // element не удалится из DOM, даже если remove() }

GC timing: // НЕ детерминирован! // НЕ определённый интервал // НЕ определённый порядок // Зависит от: engine, памяти, нагрузки


Ментальная модель

GC — как уборщик в отеле. Он приходит, когда решает (не по расписанию). Проверяет: «Есть ли кто-нибудь, кому нужна эта комната (объект)?» Если нет — забирает мебель (удаляет объект). Вы не контролируете, когда он придёт.


Примеры

**Самый простой:**

javascript
// Reachable → не удаляется
let obj = { data: 1 };
console.log(obj); // { data: 1 }

// Unreachable → GC удалит
obj = null;
// Объект { data: 1 } теперь unreachable

Доступность: если нет ссылки — объект удалится.

**Простой:**

javascript
// Memory leak: забытый listener
function setupButton() {
  const button = document.querySelector('#btn');
  const handler = () => console.log('clicked');
  button.addEventListener('click', handler);
  // Если button удалён из DOM —
  // handler и button всё ещё в памяти!
}

// Безопасно:
function safeSetup() {
  const button = document.querySelector('#btn');
  const handler = () => console.log('clicked');
  button.addEventListener('click', handler);
  return () => button.removeEventListener('click', handler);
}

Memory leak: event listener на удалённом элементе.

**Реальный пример:**

javascript
// Memory leak: замыкание с лишними данными
function createProcessor() {
  const hugeBuffer = new Array(1000000).fill(0);

  // Опасно: замыкание удерживает hugeBuffer
  return function process(smallData) {
    return smallData * 2;
    // hugeBuffer не используется, но ссылка существует!
  };
}

// Безопасно: не захватывать hugeBuffer
function createSafeProcessor() {
  const hugeBuffer = new Array(1000000).fill(0);
  const result = hugeBuffer.reduce((sum, x) => sum + x, 0);

  // hugeBuffer больше не нужен
  return function process(smallData) {
    return smallData * 2;
  };
}

Memory leak: замыкание захватывает неиспользуемые данные.


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

**Неправильно:** Думать, что GC работает с фиксированным интервалом

**Почему:** GC timing недетерминирован — зависит от engine и нагрузки.

**Правильно:** GC = когда решит движок. Нельзя предсказать или контролировать.

**Неправильно:** Полагаться на window + null для очистки

**Почему:** set window = null не очищает автоматически — GC удалит, когда решит.

**Правильно:** Устанавливайте null для создания unreachable, но не ожидайте мгновенного удаления.


Важно запомнить

  • GC удаляет unreachable объекты
  • Root: window, call stack, DOM
  • Memory leaks: listeners, globals, closures, DOM refs
  • GC timing недетерминирован
  • Минимизируйте захват переменных в замыканиях

Связь

Назад: Вы знаете объекты (J11) и типы (J3). Сборка мусора управляет памятью этих объектов.

Вперёд: Следующий урок (JV25) — полифиллы и транспиляция — как заставить новый код работать в старых средах.

Материалы курса JS Advanced — PROlab Academy.