Приклади витоків пам’яті в JavaScript та рішення

pic

  1. Забуті прослуховувачі подій (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

Leave a Reply

Your email address will not be published. Required fields are marked *