Skip to main content

Що таке витік пам'яті в JS?

1. Що таке витік пам'яті

Витік пам'яті (memory leak) - це ситуація, коли програма утримує посилання на об'єкти, які вже не потрібні, тому збирач сміття (Garbage Collector) не може звільнити їх з пам'яті.

Іншими словами:

Об'єкт більше не використовується, але через "забуті" посилання залишається в пам'яті.


2. Як працює збирач сміття (GC)

JS має автоматичну збірку сміття. GC періодично шукає "досяжні" об'єкти - ті, до яких можна дістатися за посиланнями.

Усе, до чого немає посилань (недосяжне), видаляється. Усе, на що є хоча б одне посилання, залишається в пам'яті.

Проблема витоків - коли об'єкт більше не потрібен, але десь залишилося посилання на нього → GC вважає його "живим".


3. Типові причини витоків пам'яті в JavaScript

ПричинаПрикладЩо відбувається
Глобальні змінніwindow.obj = { big: 'data' }живуть до закриття вкладки
Неочищені таймери / інтервалиsetInterval(() => {...}, 1000) без clearIntervalколбек утримує замикання і не звільняється
Слухачі подійelement.addEventListener('click', handler) без removeEventListenerелемент видалено, але обробник лишився в пам'яті
Замикання, що утримують посиланняфункції, що замикають контекст із великими об'єктамизбирач не може звільнити контекст
Кеші та структури даних (Map, Set)зростаючий Map без очищення старих ключівдані не видаляються автоматично
DOM-посилання після видалення елементаconst el = document.getElementById('app'); el.remove();, але посилання el лишилосяелемента вже немає в DOM, але він висить у пам'яті

4. Приклади витоків у коді

Глобальні змінні

javascript
function createLeak() { leak = []; // без let/const → потрапляє у window for (let i = 0; i < 1000000; i++) leak.push(i); } createLeak(); // leak живе до закриття вкладки

Таймери

javascript
function start() { const data = new Array(1e6).fill('data'); setInterval(() => console.log(data.length), 1000); } start(); // data ніколи не очищається - утримується замиканням

Обробники подій

javascript
const btn = document.getElementById('btn'); function handleClick() { console.log('clicked'); } btn.addEventListener('click', handleClick); btn.remove(); // але слухач лишився // handleClick і btn назавжди залишаться в пам'яті

Кеш без ліміту

javascript
const cache = new Map(); function heavyCalc(key) { if (cache.has(key)) return cache.get(key); const result = Array(1e5).fill(key); cache.set(key, result); // ніколи не очищається return result; }

5. Як виявити витік пам'яті

У браузері (Chrome DevTools)

  1. Відкрий вкладку Memory → "Heap snapshot".
  2. Зроби знімок пам'яті (Take snapshot).
  3. Повтори через 10-30 секунд.
  4. Порівняй: якщо "Detached DOM nodes" або об'єкти зростають → витік.

Також можна ввімкнути вкладку Performance → фільтр "Memory" → дивитися на зростання heap size.


У Node.js

  • --inspect і Chrome DevTools;
  • clinic.js, node --inspect-brk, heapdump;
  • Моніторинг heap через process.memoryUsage().

6. Як запобігати витокам

ПроблемаРішення
Глобальні зміннізавжди використовувати let, const
ТаймериclearTimeout, clearInterval при зупинці
Слухачі подійremoveEventListener при демонтуванні
Замиканняне зберігати великі об'єкти в області видимості
Кешіочищати старі записи (WeakMap, WeakSet)
DOMпри видаленні елемента прибирати посилання на нього
SPA-застосункистежити за cleanup у useEffect, onUnmount

7. "Безпечні" структури: WeakMap і WeakSet

Вони не заважають GC, бо зберігають "слабкі посилання".

javascript
let cache = new WeakMap(); function getData(obj) { if (cache.has(obj)) return cache.get(obj); const data = heavyCalculation(obj); cache.set(obj, data); return data; }

Якщо об'єкт obj більше ніде не використовується, GC видалить його автоматично, навіть якщо він є у WeakMap.


8. Ознаки витоку пам'яті

  • Поступове уповільнення застосунку;
  • Зростання пам'яті (Memory → Heap increasing);
  • Затримки в UI (особливо при скролі/рендері);
  • Часті збірки сміття (GC pauses);
  • Падіння вкладки ("Aw, Snap!") при великих обсягах даних.

9. Коротке резюме

ЩоОпис
Memory leakутримання непотрібних об'єктів у пам'яті
Причинапосилання, які не звільняються
Наслідокзростання пам'яті, лаги, падіння
ДіагностикаChrome DevTools (Memory snapshot)
Рішеннячистити таймери, слухачі, кеші, DOM-посилання
ПрофілактикаWeakMap, WeakSet, cleanup-хуки

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.