Memory leaks в браузере: как не упустить реальную проблемуУтечки памяти в JavaScript — это не только про забытые таймеры. На самом деле существует множество других скрытых причин, которые могут годами «поглощать» память. Даже опытные разработчики часто упускают эти моменты, которые становятся источниками утечек в продакшене. Сегодня разберем, какие типичные ошибки приводят к утечкам памяти и как их избегать.
Зависшие ссылки в замыканияхКогда компонент или объект был удалён, но замыкание всё равно сохраняет ссылку на данные, они не могут быть очищены. Это классическая ошибка, особенно при больших данных.
Проблема (в примерах): bigData остаётся в памяти, пока существует ссылка на колбэк.
Глобальные переменныеОшибки с глобальными переменными часто возникают, когда забывают использовать const или let.
Проблема (в примерах): Любой объект в глобальной области будет жить вечно.
Слушатели событий и DOM-узлыЕсли слушатели событий или DOM-узлы не удаляются после того, как элементы были удалены, это может привести к утечкам. Особенно часто это случается с модальными окнами или кастомными компонентами.
Проблема (в примерах): После удаления элемента слушатель остаётся, удерживая объект в памяти.
Неправильное использование таймеров
Таймеры типа setInterval, которые не очищаются при уходе со страницы, могут продолжать работать, удерживая тяжёлые данные.
Проблема: Таймер продолжает работать, сохраняя контекст.
Неправильное использование таймеров
Таймеры, такие как setInterval, могут стать серьезным источником утечек памяти, если не очищаются при уходе со страницы или продолжают ссылаться на контекст.
Проблема: Таймер продолжает работать, удерживая тяжелые данные в замыкании, даже после того, как компонент был размонтирован.
Кэши без лимитовПопытки сделать «умное кэширование» без ограничений на размер могут привести к утечкам.
Проблема (в примерах): Без лимитов на кэш память будет заполняться бесконечно.
Проблемы с Web WorkersОшибки в работе с Web Workers, такие как передача данных без Transferables или не закрытые воркеры, могут стать причиной утечек.
Сторонние библиотекиНекоторые библиотеки, особенно для UI, могут создавать скрытые DOM-структуры и не очищать их по завершении работы, что также ведет к утечкам.
React: stale effectsВ React утечки могут происходить из-за старых ссылок в эффектах, которые не пересоздаются.
Проблема (в примерах): Эффект не пересоздается, старые ссылки остаются.
Примеры// Зависшие ссылки в замыканиях
function createTracker() {
const bigData = new Array(1_000_000).fill('x');
return () => console.log(bigData.length);
}
// Глобальные переменные
foo = {}; // теперь это window.foo
// Слушатели событий и DOM-узлы
element.addEventListener('scroll', handler);
// element.removeEventListener(...) забыли
// Кэши без лимитов
const cache = {};
cache[key] = heavyObject;
// React: stale effects
useEffect(() => {
subscribe();
return () => unsubscribe();
}, []); // но зависимость должна быть!
Для обнаружения утечек памяти используйте Chrome DevTools. Перейдите в Performance → Memory Leak Check и проанализируйте Heap snapshots и Allocation Timelines. Обращайте внимание на Detached DOM nodes и Large object groups. Утечка памяти происходит, когда объект больше не нужен, но на него всё ещё есть ссылка. Иногда это баг, который длится месяцами.
Frontender's note
3.48K views14:37