Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Управление памятью в JavaScript
Garbage Collection (GC) - это автоматический механизм в JavaScript, который освобождает память, удаляя объекты, которые больше не используются.
1. Основной принцип: Reachability
// Объект доступен (reachable), если его можно получить из корня
let user = {
name: "Alice",
email: "alice@example.com"
};
// user доступен из глобального контекста
// Его память не будет освобождена
// Если переменная больше не содержит ссылку на объект:
user = null; // Теперь объект недоступен
// GC удалит объект из памяти
// Статистика памяти
console.log(performance.memory);
// heapSizeLimit: максимальный размер heap
// totalJSHeapSize: текущий размер heap
// usedJSHeapSize: используемая память
2. Алгоритм Mark and Sweep
// Это основной алгоритм GC в современных браузерах
// Шаг 1: Mark (пометка)
// GC проходит по всем объектам и помечает доступные
// Шаг 2: Sweep (удаление)
// GC удаляет объекты, которые не помечены
// Пример:
let a = { value: 1 };
let b = { value: 2 };
let c = a; // c указывает на тот же объект что и a
a = null; // a больше не использует объект
b = null; // b больше не использует свой объект
// Объект { value: 1 } всё ещё доступен через c
// Объект { value: 2 } недоступен - будет удалён GC
c = null; // Теперь оба объекта недоступны
// GC удалит оба объекта
3. References и циклические ссылки
// Старые браузеры с Reference Counting имели проблемы с циклами
// ПРОБЛЕМА в старых браузерах:
let parent = {};
let child = {};
parent.child = child;
child.parent = parent; // Циклическая ссылка
parent = null;
child = null;
// В алгоритме Mark and Sweep это не проблема
// Но в Reference Counting объекты не удаляются (утечка памяти)
// Mark and Sweep удаляет оба объекта, так как они недоступны
4. Утечки памяти (Memory Leaks)
// УТЕЧКА: Ненужные глобальные переменные
window.largeArray = new Array(1000000).fill('data');
// Массив никогда не удалится, занимает память
// УТЕЧКА: Забытые listener
const button = document.querySelector('button');
button.addEventListener('click', () => {
console.log('Clicked');
});
// Listener остаётся даже если элемент удалён из DOM
// ИСПРАВЛЕНИЕ: Удаляй listener
button.removeEventListener('click', handler);
// УТЕЧКА: Бесконечные таймеры
setInterval(() => {
console.log('Every second');
}, 1000);
// Никогда не останавливается
// ИСПРАВЛЕНИЕ: Сохраняй ID и очищай
const timerId = setInterval(() => { }, 1000);
clearInterval(timerId);
5. Утечки в React
// УТЕЧКА: useEffect без очистки
export function UserCard({ userId }) {
useEffect(() => {
const timer = setInterval(() => {
console.log('Update');
}, 1000);
// Таймер никогда не очистится!
// При unmount компонента утечка
}, [userId]);
return <div>User</div>;
}
// ИСПРАВЛЕНИЕ: Возврати cleanup функцию
export function UserCard({ userId }) {
useEffect(() => {
const timer = setInterval(() => {
console.log('Update');
}, 1000);
return () => clearInterval(timer); // Очистка
}, [userId]);
return <div>User</div>;
}
// УТЕЧКА: Listener на события
export function Observer({ onData }) {
useEffect(() => {
window.addEventListener('message', onData);
// Listener не удаляется
}, [onData]);
return <div>Observer</div>;
}
// ИСПРАВЛЕНИЕ
export function Observer({ onData }) {
useEffect(() => {
window.addEventListener('message', onData);
return () => window.removeEventListener('message', onData);
}, [onData]);
return <div>Observer</div>;
}
6. WeakMap и WeakSet
// WeakMap хранит слабые ссылки на объекты
// Объекты могут быть удалены GC даже если они в WeakMap
const cache = new WeakMap();
let user = { id: 1, name: 'Alice' };
cache.set(user, { cached: true });
console.log(cache.get(user)); // { cached: true }
user = null; // Объект может быть удалён GC
// Запись в WeakMap также удалится
// Обычный Map хранит сильные ссылки
const strongCache = new Map();
let obj = { id: 1 };
strongCache.set(obj, 'data');
obj = null; // Объект НЕ удалится, остаётся в Map
7. Профилирование памяти
// Chrome DevTools: Memory tab
// Snapshot - снимок памяти
// Allocation timeline - как растёт память
// Allocation profiler - какие объекты занимают память
// Вручную вызови GC (если DevTools открыт в специальном режиме)
if (window.gc) {
gc(); // Принудительная сборка мусора
}
// Проверь память
console.log(performance.memory.usedJSHeapSize); // Текущее использование
// Поищи утечки
const arr = [];
for (let i = 0; i < 1000000; i++) {
arr.push({ data: new Array(100).fill('x') });
}
// Как растёт usedJSHeapSize при добавлении?
8. Оптимизация для GC
// ПЛОХО: Создание много объектов
function render() {
for (let i = 0; i < 1000; i++) {
const point = { x: Math.random(), y: Math.random() };
processPoint(point);
}
}
// ХОРОШО: Переиспользуй объекты
const point = { x: 0, y: 0 };
function render() {
for (let i = 0; i < 1000; i++) {
point.x = Math.random();
point.y = Math.random();
processPoint(point);
}
}
// ПЛОХО: Создание больших объектов в цикле
for (let i = 0; i < 100; i++) {
const data = new Array(10000).fill(0);
}
// ХОРОШО: Переиспользуй буфер
const buffer = new Array(10000);
for (let i = 0; i < 100; i++) {
buffer.fill(0);
}
9. Поколенческий GC
// Современные браузеры используют поколенческий GC
// Young generation - новые объекты (часто собираются)
// Old generation - старые объекты (редко собираются)
// Новый объект
let young = { id: 1 };
// После нескольких GC циклов переходит в Old generation
young.id = 2; // Переходит в Old
young.id = 3;
young.id = 4;
// Объекты в Old собираются реже, т.к. обычно долгоживущие
// Это оптимизирует производительность
Ответ: GC использует алгоритм Mark and Sweep для удаления недоступных объектов. Профилируй утечки в DevTools, очищай listener в useEffect, и избегай глобальных переменных.