JavaScript автоматически управляет памятью через Garbage Collector (GC). Разработчику не нужно вручную освобождать память, но нужно понимать, как GC решает, что объект можно удалить, чтобы избегать утечек.
Алгоритм пометки (Mark and Sweep)
Современные движки (V8, SpiderMonkey) используют алгоритм «Reachability» (Достижимость). Объект считается «мусором», если на него нет ссылок из корня (root). Корнями являются глобальный объект window, стек вызовов функций и т.д.
function leak() {
let data = new Array(1000000);
// Если data не вернуть и не сохранить глобально,
// после выхода из функции она станет недостижимой
}
leak(); // Память освободится
Проблемы возникают, когда ссылки сохраняются непреднамеренно.
Типичные утечки памяти
- Глобальные переменные: Случайное создание свойств на
window. - Таймеры и колбэки: Забытый
setIntervalили слушатель событий на элементе, который удален из DOM. - Замыкания: Как обсуждалось ранее, длинные замыкания удерживают контекст.
// Пример утечки через слушатель
const btn = document.getElementById('btn');
btn.addEventListener('click', function heavyHandler() {
// Логика
});
// Если btn удалить из DOM, но не удалить слушатель (removeEventListener),
// heavyHandler и всё, что он замыкает, останется в памяти.
Инструменты диагностики
В Chrome DevTools вкладка Memory позволяет делать снимки (Heap Snapshots). Сравнивая снимки до и после действия, можно найти объекты, которые не были удалены. Ищите растущее количество деташедных (detached) DOM-элементов.
Регулярный профайлинг помогает находить утечки до того, как пользователи начнут жаловаться на тормоза.