- Забуті прослуховувачі подій (Event Listeners)
- Проблема: Коли ви додаєте прослуховувачі подій (Event Listeners), але ніколи їх не видаляєте, вони продовжують утримувати пам'ять, навіть якщо вони більше не потрібні.
- Рішення: Завжди створюйте метод для очищення, щоб видаляти прослуховувачі подій (Event Listeners), коли ви з ними закінчили.
- Приклад з реального життя: Це схоже на підписку на журнал — якщо ви переїхали в інше місто, але не скасували підписку, журнали продовжують приходити на вашу стару адресу.
// ✅ Хороша практика: Очищення прослуховувачів подій (Event Listeners)
class BetterNewsletterWidget {
constructor() {
this.button = document.querySelector('#subscribe');
// Прив'язуємо метод, щоб зберегти посилання
this.boundHandler = this.handleSubscribe.bind(this);
this.button.addEventListener('click', this.boundHandler);
}
handleSubscribe() {
// Логіка підписки
}
// Очищення, коли все зроблено
destroy() {
this.button.removeEventListener('click', this.boundHandler);
}
}
2. Помилкові глобальні змінні
- Проблема: Коли ви забуваєте використовувати
let
абоconst
, JavaScript створює глобальні змінні, які залишаються в пам'яті. - Рішення: Завжди правильно оголошуйте змінні за допомогою
let
абоconst
. - Приклад з реального життя: Це схоже на те, як залишити свої речі в громадському місці замість вашої приватної кімнати.
function createUser() {
// ❌ Погана практика: Відсутність 'let' або 'const' створює глобальну змінну
user = { name: 'John', age: 30 };
}
// ✅ Хороша практика: Правильне оголошення змінних
function createUserBetter() {
const user = { name: 'John', age: 30 };
return user;
}
3. Циклічні посилання
- Проблема: Коли два об'єкти посилаються один на одного, створюючи нескінченний цикл.
- Рішення: Використовуйте
WeakMap
для зберігання посилань, що дозволяє об'єктам бути зібраними сміттєзбиральником. - Приклад з реального життя: Як двоє друзів, які тримаються за мотузку — жоден не може відпустити, поки хтось не розрізає мотузку.
// ❌ Погана практика: Об'єкти, що посилаються один на одного
let student = {
name: 'Alice'
};
let course = {
title: 'JavaScript'
};
// Створюємо циклічне посилання
student.enrolledCourse = course;
course.enrolledStudent = student;
// ✅ Хороша практика: Використовуємо WeakMap для посилань
const studentCourses = new WeakMap();
let betterStudent = {
name: 'Alice'
};
let betterCourse = {
title: 'JavaScript'
};
// Зберігаємо посилання у WeakMap
studentCourses.set(betterStudent, betterCourse);
5. Забуті інтервали
- Проблема: Початок інтервалів (наприклад, таймерів), але ніколи їх не зупиняєте.
- Рішення: Завжди зберігайте ідентифікатори інтервалів і очищайте їх, коли вони більше не потрібні.
- Приклад з реального життя: Це як залишити машину працювати на парковці — вона продовжує витрачати паливо, поки ви її не вимкнете.
function betterCounter() {
let count = 0;
const intervalId = setInterval(() => {
console.log('Counting:', count++);
if (count > 10) {
clearInterval(intervalId);
}
}, 1000);
return intervalId;
}
5. Замикання, що утримують посилання
- Проблема: Функції, що зберігають посилання на великі дані навіть після того, як вони більше не потрібні.
- Рішення: Явно очищайте посилання, коли ви з ними закінчили.
- Приклад з реального життя: Це як тримати величезний фотоальбом у своєму рюкзаку, хоча вам потрібна тільки одна фотографія.
// ❌ Погана практика: Замикання утримує посилання на великі дані
function processData() {
const hugeData = new Array(1000000).fill('🐘');
return function() {
console.log('Data length:', hugeData.length);
};
}
// ✅ Хороша практика: Очищення посилань, коли все зроблено
function betterProcessData() {
let hugeData = new Array(1000000).fill('🐘');
const result = function() {
console.log('Data length:', hugeData.length);
};
// Очищення посилання
const cleanup = () => {
hugeData = null;
};
return { result, cleanup };
}
**Посилання на елементи DOM (DOM References)**
- Проблема: Зберігання посилань на елементи DOM (DOM) які можуть бути видалені.
- Рішення: Використовуйте `WeakRef` для посилань на елементи DOM (DOM), щоб вони могли бути зібрані сміттєзбиральником після видалення елементів.
- Приклад з реального життя: Це схоже на зберігання адрес магазинів, що вже закрилися.
const elements = {
header: new WeakRef(document.querySelector('header')),
sidebar: new WeakRef(document.querySelector('sidebar'))
};
// Безпечно отримуємо елементи
function getElement(key) {
const element = elements[key].deref();
return element ? element : null;
}
```
Бажаєте дізнатися більше подібного контенту?
Підпишіться на мене або напишіть мені в Linkedin.
Перекладено з: JavaScript Memory Leak Examples and Solutions