> Как работает сборщик мусора в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Верме, ITFB, Сбер, Арго, SmartWay, ООО Снэп АйТи

Стек: JavaScript

> Пример ответа

Короткий ответ

Сборщик мусора в JavaScript автоматически освобождает память, удаляя объекты, на которые нет активных ссылок. Основной алгоритм - mark-and-sweep: сборщик обходит граф объектов от корневых ссылок (глобальный объект, локальные переменные) и помечает все достижимые объекты, затем удаляет непомеченные. Современные движки (V8, SpiderMonkey) используют поколенческую сборку и инкрементальные проходы для минимизации пауз.

Подробное объяснение

Сборщик мусора (GC) в JS основан на концепции достижимости. Объект считается "живым", если он достижим из корневых ссылок через цепочку свойств. Корни - это глобальный объект (window/global), текущий стек вызовов (локальные переменные, аргументы функций) и замыкания. Когда объект становится недостижимым, GC освобождает занимаемую им память.

Основной алгоритм - mark-and-sweep:

  1. Mark phase: GC стартует от корней и рекурсивно обходит все ссылки, помечая каждый достижимый объект.
  2. Sweep phase: непомеченные объекты удаляются, их память возвращается в heap.

Современные движки (V8 в Chrome/Node.js) используют поколенческую сборку:

  • Young generation (nursery): для недавно созданных объектов. Сборка происходит часто и быстро (Scavenge - копирование живых объектов в survivor space).
  • Old generation: для объектов, переживших несколько сборок. Используется mark-sweep и mark-compact (дефрагментация).

Оптимизации:

  • Incremental GC: разбивает mark phase на мелкие шаги между выполнением JS, чтобы избежать длительных пауз.
  • Concurrent marking: mark phase выполняется параллельно с основным потоком (в V8).
  • Idle-time GC: сборка запускается в периоды простоя event loop.

На практике

Для senior-разработчика важно понимать, как GC влияет на производительность:

  • Утечки памяти: глобальные переменные, забытые таймеры/колбэки, замыкания, удерживающие большие объекты, detached DOM nodes (ссылки из JS на удалённые элементы).
  • Паттерны для оптимизации: обнуление ссылок (obj = null), использование WeakMap/WeakSet для кэшей (не блокируют GC), избегание циклических ссылок (хотя mark-and-sweep их обрабатывает).
  • Инструменты: Chrome DevTools (Memory tab - heap snapshot, allocation timeline, performance), Node.js (--inspect, heapdump).

Пример кода

JAVASCRIPT
// Утечка через замыкание
function createLeak() {
const largeData = new Array(1000000).fill('x');
return function() {
console.log(largeData.length); // largeData не будет собран, пока жив callback
};
}
// Правильное использование WeakMap для кэша
const cache = new WeakMap();
function process(obj) {
if (!cache.has(obj)) {
cache.set(obj, expensiveComputation(obj));
}
return cache.get(obj);
}
// Когда obj удаляется извне, запись в WeakMap автоматически становится недостижимой

Как отвечать на собеседовании

Начни с краткого определения mark-and-sweep, затем углубись в поколенческую сборку и оптимизации. Упомяни разницу между V8 и старыми движками (например, reference counting в IE - проблема циклических ссылок). Приведи пример утечки и способа её избежать. Покажи понимание trade-off: частота сборки vs паузы, влияние на real-time приложения (анимации, игры). Используй термины: reachability, root set, young/old generation, scavenge, mark-compact.

Что проверяет интервьюер

  • Понимание фундаментального механизма управления памятью в JS.
  • Знание практических проблем (утечки) и инструментов отладки.
  • Способность объяснить сложные концепции (поколения, инкрементальность) простым языком.
  • Опыт оптимизации производительности с учётом GC.

Типичные ошибки

  • Утверждение, что JS использует reference counting (это устаревший подход, не применяется в современных движках).
  • Игнорирование поколенческой сборки и фокус только на mark-and-sweep.
  • Непонимание, что WeakMap/WeakSet не предотвращают GC, а наоборот - позволяют ему работать.
  • Ошибка: "нужно вручную вызывать GC" - в JS нет публичного API для принудительного запуска (кроме --expose-gc в Node.js для отладки).

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью