Кратко
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 — как уборщик в отеле. Он приходит, когда решает (не по расписанию). Проверяет: «Есть ли кто-нибудь, кому нужна эта комната (объект)?» Если нет — забирает мебель (удаляет объект). Вы не контролируете, когда он придёт.
Примеры
**Самый простой:**
// Reachable → не удаляется
let obj = { data: 1 };
console.log(obj); // { data: 1 }
// Unreachable → GC удалит
obj = null;
// Объект { data: 1 } теперь unreachableДоступность: если нет ссылки — объект удалится.
**Простой:**
// 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 на удалённом элементе.
**Реальный пример:**
// 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) — полифиллы и транспиляция — как заставить новый код работать в старых средах.