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

Какие объекты кучи помечаются сборщиком мусора?

1.7 Middle🔥 111 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

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

Принцип работы сборщика мусора в JavaScript

В JavaScript сборщик мусора (Garbage Collector) автоматически управляет памятью, освобождая ресурсы, которые больше не используются программой. В отличие от языков с ручным управлением памятью (как C/C++), разработчику не нужно явно выделять и освобождать память.

Какие объекты попадают в кучу (heap)

Куча — это область динамической памяти, где хранятся:

  • Объекты ({}, new Object())
  • Массивы ([], new Array())
  • Функции (кроме примитивов)
  • Замыкания и их окружения
  • DOM-элементы (в браузере)
  • Ссылочные типы данных вообще
// Все эти создания помещают данные в кучу:
const user = { name: 'Alex', age: 30 }; // Объект в куче
const list = [1, 2, 3]; // Массив в куче
const func = () => console.log('hello'); // Функция в куче
const element = document.createElement('div'); // DOM-элемент в куче

Критерии пометки объектов для сборки мусора

Сборщик мусора помечает для удаления объекты, которые недостижимы из корневых точек. Основные алгоритмы — mark-and-sweep (пометка и очистка) и его оптимизированные версии.

Корневые точки (roots) — то, что всегда достижимо:

  • Глобальный объект (window в браузере, global в Node.js)
  • Активный контекст выполнения (локальные переменные и параметры функций)
  • Ссылки из текущего стека вызовов
  • Встроенные объекты (например, корни DOM)

Примеры помечаемых объектов:

1. Объекты без ссылок:

function createData() {
    const temp = { x: 10, y: 20 }; // Создается объект в куче
    // После выхода из функции temp становится недостижим
    // и будет помечен сборщиком мусора
}
createData();

2. Перезаписанные ссылки:

let data = { id: 1 };
data = { id: 2 }; // Первый объект {id: 1} теряет ссылку и помечается

3. Циклические ссылки без внешних связей:

function createCycle() {
    const a = { name: 'A' };
    const b = { name: 'B' };
    a.ref = b;
    b.ref = a; // Циклическая ссылка
    // Но после выхода из функции оба объекта недостижимы из корней
    // и БУДУТ собраны (современные сборщики справляются с циклами)
}
createCycle();

4. Замыкания, которые больше не используются:

function outer() {
    const largeData = new Array(1000000).fill('data');
    return function inner() {
        console.log('hello');
        // largeData все еще доступна для inner через замыкание
    };
}
const fn = outer();
// Пока fn существует, largeData не будет собрана
fn = null; // Теперь и inner, и largeData могут быть помечены

Что НЕ будет помечено (и останется в памяти):

  1. Глобальные переменные:
window.cache = { users: [] }; // Будет висеть пока живет window
  1. Активные ссылки из DOM:
const button = document.getElementById('myButton');
button.data = { clicks: 0 }; // Объект привязан к DOM-элементу
// Даже если в коде нет ссылки на button.data, 
// он достижим через DOM и не соберется
  1. Таймеры и обработчики событий:
const object = { data: 'important' };
setInterval(() => {
    console.log(object.data); // object все еще достижим через замыкание
}, 1000);

Практические рекомендации для разработчиков

  1. Явно обнуляйте ссылки в больших приложениях:
let heavyData = new Array(1000000);
// Когда данные больше не нужны:
heavyData = null; // Помогает сборщику понять, что можно очистить
  1. Избегайте утечек памяти через замыкания:
function process() {
    const data = getLargeData();
    // Плохо: элемент button будет хранить ссылку на data
    button.onclick = () => useData(data);
    
    // Лучше: если data не нужна, обработать сразу
    const result = processData(data);
    button.onclick = () => useResult(result);
}
  1. Используйте WeakMap и WeakSet для кеширования:
// WeakMap позволяет собирать ключи, если на них нет других ссылок
const cache = new WeakMap();
const user = { id: 1 };
cache.set(user, expensiveCalculation(user));
// Если объект user удалится, запись автоматически удалится из WeakMap

Особенности в современных движках

Современные сборщики мусора (V8, SpiderMonkey) используют поколенческую сборку:

  • Молодое поколение — краткоживущие объекты, сборка происходит часто
  • Старое поколение — долгоживущие объекты, сборка происходит реже
  • Инкрементальная и параллельная сборка — минимизация пауз

Объект будет помечен и удален тогда, когда он недостижим из любого корня через цепочку ссылок, независимо от циклических зависимостей внутри самой недостижимой группы объектов.

Понимание этих принципов критично для создания производительных Frontend-приложений, особенно работающих с большими объемами данных, такими как SPA, графические редакторы или веб-игры.