Как хранятся значения и объекты в памяти heap & stack

Stack & heap

  • Heap(куча) - Мы уже знакомы с кучей, и в первом уроке этого руководства говорили о том, что в куче хранятся все объекты и функции, и то, что здесь используется динамическое выделение памяти. Динамическое оно потому, что движок не знает, сколько ему понадобится памяти под тот или иной объект, а потому выделяет память по мере необходимости.

  • Stack - Примитивные значения в свою очередь хранятся в контексте выполнения, а память для них выделяется на этапе создания до выполнения кода. Это связано с тем, что для примитивных значений существует фиксированный объем памяти. Это понятие часто упрощается до термина стек, чтобы избежать каждый раз упоминания конкретного контекста выполнения. Различные контексты выполнения взаимосвязаны и могут быть представлены структурой данных stack(стек).

Примитивные значения

Теперь посмотрим на примере как это работает:

let a = 1;
stack&heap_start_position

Первом делом javascript движок создаст идентификатор a - то есть переменную. Далее будет выделена память по определенному адресу(в моем случае это псевдо адрес) и после в память по этому адресу будет помещено значение.

  • Если говорить о переменной в общем, то переменная хранит значение, а не адрес в памяти. Но в javascript в техническом плане, переменная представляет собой ссылку на место в памяти, где хранится значение. Это свойство языка, а не характеристика переменной как таковой.

Добавим еще переменную и присвоем ей переменную a.

let a = 1;
let b = a;
stack-heap/stack&heap_start_create_variable_b

Теперь переменная b ссылается на тот же адрес, что и переменная a. Но что будет если мы перезапишем переменную a?

let a = 1;
let b = a;
a = 2;
console.log(a); // 2
console.log(b); // 1
stack-heap/stack&heap_start_create_variable_b

В таком случае выделяется новый кусочек памяти, после этого переменная a указывает уже на новый адрес, с новым значением. В свою очередь, переменная b указывает на старый адрес.

  • Примитивные значения в javascript иммутабельны(неизменны), они хранятся в памяти как константы и не могут быть изменены после создания. Когда мы создаем переменную и присваиваем ей значение 1, это значение будет храниться в памяти как константа с типом number. При изменении выделяется новый кусочек памяти в котром будет содержаться новое значение.

Ссылочные значения

Теперь посмотрим на объект.

const anime = {
    name: 'gintama',
    seasons: 8
};
stack-heap/stack&heap_start_create_variable_b

В таком случае у нас в стеке создается идентификатор с новым адресом в памяти, который хранит в себе адрес на объект в куче. Теперь попробуем создать еще объект и присвоим ему объект anime.

const anime = {
    name: 'gintama',
    seasons: 8
};

const newAnime = anime;
newAnime.name = 'trigun';


console.log(anime.name); // trigun
console.log(newAnime.name); // trigun
stack-heap/stack&heap_start_create_variable_b

В таком случае, новая переменная, как и в примере со значениями, будет ссылаться на тот же адрес в стеке, который, в свою очередь, уже ссылается на адрес в куче. При этом, неважно, что мы объявили объект через const, мы не меняем значение внутри переменной newAnime - значение этой переменной это ссылка на объект в куче и эта ссылка остается нетронутой, мы меням значение, которое находится в куче.

05.04.2022