
Факт: Память — ограниченный ресурс. Учитывая это, важно понимать, сколько памяти использует наше приложение или программа и как управлять этой памятью, чтобы обеспечить производительность и эффективность.
В отличие от языков низкого уровня, таких как C, которые имеют ручное управление памятью, память в JavaScript в основном обрабатывается движком JavaScript. Он автоматически выделяет память, когда мы создаем объекты, строки и другие типы данных, и освобождает ее, когда она больше не используется.
В этой статье более подробно рассматривается, что происходит под капотом, приводятся примеры реального кода, которые помогут вам лучше выявлять шаблоны в управлении памятью и не отставать от лучших практик.
Давайте приступим!
Почему мы должны заботиться о памяти

- Память — это ограниченный ресурс. Поскольку люди платят за машины с большим объемом памяти, они ожидают лучшего опыта, а это означает эффективное использование памяти.
- Другая сторона медали производительности: программы считаются эффективными по тому, насколько быстро они работают и сколько памяти мы используем.
- Мониторинг производительности и анализ памяти. Одним из инструментов, предоставляемых chrome devtools, является панель памяти, где вы можете исследовать любые проблемы с памятью в вашем приложении.
- Создайте лучший веб-опыт. При работе с процессами, интенсивно использующими память, такими как обработка изображений и веб-анимация, важно знать, как исправить проблемы с памятью, такие как утечки памяти, которые возникают довольно часто.
Жизненный цикл памяти
Жизненный цикл памяти одинаков во всех языках программирования:
- Сначала мы выделяем память либо вручную, либо путем создания переменной.
- Затем мы используем выделенную память (чтение/запись)
- Освободите память, когда она больше не используется

Память стека
Память стека — это упорядоченное место для вставки, использующее структуру данных стека по принципу LIFO (последним пришел — первым вышел). Когда функции добавляются в стек, функция, переданная в стек последней, выполняется первой.
Память стека хранит статические данные, т. е. размер данных известен во время компиляции. Сюда входят примитивные типы и ссылки. Ограничения памяти стека зависят от браузера. Некоторые важные вещи, которые следует отметить:
- Примитивные типы хранятся непосредственно в стеке. Для отслеживания текущего места в памяти существует специальный регистр процессора, который называется Указатель стека. Это указатели на объекты/функции, расположенные в куче памяти.
- Все локальные переменные, включая аргументы и возвращаемое значение функций, хранятся в блоке функционального фрейма в стеке. Когда вы выходите из функции, все, что связано с этой функцией, удаляется из стека.
- Разработчики не контролируют память стека, ею управляет движок JavaScript.

Переполнение стека
Переполнение стека происходит, когда стек превышает максимальный размер. Это может произойти, когда есть бесконечный цикл или рекурсивные функции, которые не возвращаются.

Куча памяти
В отличие от памяти стека, память кучи не упорядочена, вы выделяете память везде, где можете. Он в основном используется для хранения объектов, а память выделяется динамически.
Динамическое выделение памяти означает, что память выделяется по мере необходимости, т. е. механизм JS не выделяет фиксированный объем памяти. Это выполняется во время выполнения, поскольку размер выделяемой памяти неизвестен во время компиляции.
// example of dynamic memory allocation let arr = []; // empty array arr = Array(20).fill(1); // allocates more memory to arr, to hold 20 integers
Объект может хранить память двумя способами:
- Непосредственно самим объектом.
- Неявно, сохраняя ссылки на другие объекты и, следовательно, предотвращая автоматическое удаление этих объектов сборщиком мусора.
const person = {}; // the objects holds the memory
const newPerson = person; // holds reference to person object
Некоторые из проблем, возникающих с памятью кучи, заключаются в том, что со временем она фрагментируется. Свободного места может быть достаточно, но небольшими кусками. Хороший пример: нам нужно 2 Гб памяти для одного объекта, но у нас есть 2 Гб кусками по 200 Мб в куче. В большинстве современных браузеров есть алгоритмы, позволяющие лучше справляться с этим.

Вывоз мусора
Сборка мусора относится к процессу автоматического освобождения памяти, когда она больше не используется. Он использует сборщики мусора, которые представляют собой программное обеспечение, используемое для отслеживания выделения и использования памяти, чтобы определить, когда часть выделенной памяти больше не нужна, и в этом случае она освободит память, занятую этот объект.
Примеры кода
/* --- allocates memory for a string --- */
let name = "Pam";
/*
Primitive values are immutable, which means that instead of changing the
original value, JavaScript creates a new one.
The line below, allocates memory for a new string
*/
name = "Jim";
/* --- Memory allocation on heap --- */
/* -- Objects located in heap will have a stack pointer that references them -- */
/* -- allocate memory in heap for our function(object) -- */
const logName = () => console.log(name);
/* -- allocate memory in heap for our object -- */
const Person = {
name: "Oscar",
age: 101
}
/* -- allocate memory in heap for our array(object) -- */
const colleagues = ["Kelly", "Ryan"];
/* allocate more memory for colleagues array */
colleagues.push("Michael");
/* --- garbage collection & reference --- */
const logName = () => {
// variable created in function frame block on stack memory
const name= "Dwight";
console.log(name);
}
/* -- Once logName function is executed and popped off the stack, name is garbage collected as it's no longer referenced -- */
/* -- Variable created on global scope/window object. Will not be garbage collected -- */
tv_show = "The Office";
window.tv_show; // returns "The Office"
// to free this memory
window.tv_show = null;
Доступ к объектам всегда осуществляется по ссылке. По этой причине, даже если объект имеет точно такие же свойства, они не считаются равными, поскольку указывают на разные объекты в куче памяти.

Утечки памяти
Утечки памяти — это участки памяти, которые приложение использовало в прошлом и которые больше не нужны, но еще не возвращены обратно в пул свободной памяти. Таким образом, он становится недоступным для новых объектов и часто недоступным для сборки мусора. Это также может привести к ошибке, если вашему браузеру не хватает памяти.
Некоторые распространенные причины утечек памяти включают в себя:
- Глобальные переменные. Глобальные переменные прикрепляются к объекту окна и существуют на время выполнения программы. Поскольку глобальный контекст имеет ссылку на себя, они всегда хранятся в памяти и поэтому не собираются.
- Забытые таймеры и обратные вызовы. Когда вы настраиваете прослушиватель событий или функцию setInterval для выполнения каждые x секунд, это может привести к увеличению использования памяти приложением.

Заключение
Надеюсь, вы узнали немного больше о том, что происходит под капотом и как JavaScript Engine управляет памятью. Подпишитесь на меня, чтобы быть в курсе следующей статьи из этой серии, в которой мы подробно расскажем о процессе сборки мусора.
Спасибо за прочтение. Если у вас есть мысли по этому поводу, обязательно оставьте комментарий.
Если эта статья оказалась для вас полезной, не забудьте поставить хлопки 👏.
Повышение уровня кодирования
Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:
- 👏 Хлопайте за историю и подписывайтесь на автора 👉
- 📰 Смотрите больше контента в публикации Level Up Coding
- 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
- 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"
🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу