Бережное программирование
Рекомендации по предотвращению утечек памяти в JavaScript
Для предотвращения утечек памяти в JavaScript необходимо контролировать несколько ключевых аспектов и придерживаться рекомендаций:
  • Избегайте глобальных переменных
  • Очищайте массивы и объекты
  • Удаляйте обработчики событий
  • Избегайте замыканий, удерживающих большие объекты
  • Проверяйте корректность работы с таймерами
  • Избегайте утечек в асинхронных операциях
  • Контролируйте DOM-элементы
  • Используйте слабые карты (WeakMap)
Рекомендации и примеры
1. Избегайте использования глобальных переменных
Глобальные переменные остаются в памяти на протяжении всего времени работы приложения.

//Пример
var globalVar = 'I am global';

//Решение
//Используйте локальные переменные внутри функций или модулей.
(function() {
    let localVar = 'I am local';
})();

2. Очищайте массивы и объекты
Большие массивы и объекты, которые не очищаются должным образом, могут потреблять много памяти.

//Пример и решение
data.length = 0;

3. Удаляйте обработчики событий
Не удаленные обработчики событий могут удерживать ссылки на объекты.

//Пример
element.addEventListener('click', function() {
    // Длительная операция
});

//Решение:
//Удаляйте обработчики событий, когда они больше не нужны.
function handleClick() {
    // Длительная операция
}
element.addEventListener('click', handleClick);

// Позже, когда обработчик больше не нужен
element.removeEventListener('click', handleClick);

4. Избегайте замыканий, удерживающих большие объекты
Замыкания могут удерживать ссылки на объекты, даже если они больше не используются.

//Пример
function createHandler() {
    let largeObject = new Array(10000).join('x');
    return function() {
        console.log(largeObject);
    };
}
document.getElementById('myButton').addEventListener('click', createHandler());

//Решение:
//Убедитесь, что замыкания не удерживают лишние данные.
function createHandler() {
    let largeObject = new Array(10000).join('x');
    return function() {
        largeObject = null;  // Освобождаем память
        console.log('Handler called');
    };
}
document.getElementById('myButton').addEventListener('click', createHandler());

5. Проверяйте корректность работы с таймерами
Таймеры (`setInterval`, `setTimeout`) могут продолжать работать и удерживать ссылки на объекты.

//Пример
let timer = setInterval(function() {
    // Длительная операция
}, 1000);

//Решение:
//Очищайте таймеры, когда они больше не нужны.
clearInterval(timer);

6. Избегайте утечек в асинхронных операциях
Асинхронные операции, такие как AJAX-запросы, могут привести к утечкам памяти, если они не управляются должным образом.

//Пример
function fetchData() {
    fetch('https://example.com')
        .then(response => response.json())
        .then(data => {
            // Обработка данных
        });
}
fetchData();

//Решение:
//Убедитесь, что обработчики правильно управляют ресурсами и очищают данные.
function fetchData() {
    fetch('https://example.com')
        .then(response => response.json())
        .then(data => {
            // Обработка данных
        })
        .catch(error => {
            console.error('Error:', error);
        });
}
fetchData();

7. Контролируйте DOM-элементы
Убедитесь, что удаленные элементы DOM не удерживаются в памяти.

//Пример
let element = document.getElementById('myElement');
element.remove();

//Решение:
//Удаляйте ссылки на удаленные элементы DOM.
element.parentNode.removeChild(element);
element = null;  // Убедитесь, что элемент больше не удерживается

8. Используйте слабые карты (WeakMap)
Используйте `WeakMap` для объектов, которые должны быть собраны сборщиком мусора, если больше нет других ссылок на них.

//Пример
let map = new Map();
let obj = {};
map.set(obj, 'value');

//Решение:
//Используйте `WeakMap`, если объекты должны быть автоматически удалены из памяти.
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, 'value');
// Когда obj больше не существует, запись в weakMap будет удалена автоматически

Заключение
Контроль за использованием памяти в JavaScript требует внимания к деталям, таким как область видимости переменных, управление обработчиками событий, работа с асинхронными операциями и очистка ресурсов. Следование нашим рекомендациям поможет минимизировать утечки памяти и улучшить производительность вашего приложения.