Введение
В вычислительной технике значение — часть данных, которые компьютерная программа может хранить и которыми она может манипулировать. Оно хранится в памяти и может быть легко извлечено.
Значение хранится в памяти как сигнал (последовательность битов).
JavaScript — это интерпретируемый язык, компилируемый в режиме Just-In-Time (JIT), то есть во время выполнения.
Значение, о котором идет речь, хранится в ячейке памяти с адресом. Мы не можем запомнить адреса ячеек памяти. Поэтому нужно найти способ обозначить эти места. Имена переменных и констант помогают в этом.
Переменные (и константы)
Переменные — идентификаторы, используемые для определения места хранения значения в памяти. Значение, хранящееся в ячейке памяти (обозначается как переменная), может быть изменено, в то время как значение, обозначенное как константа, изменить нельзя.
На высоком уровне переменную (и константу) можно рассматривать как способ определения местоположения хранимого значения.

Рассмотрим изображенную выше диаграмму: если предположить, что вся сетка — это память, то при сохранении значения в закрашенной области адрес будет b1. Обозначим его так для демонстрации. Обычно адреса указываются в шестнадцатеричном виде. Если десять таких областей памяти будут заполнены значениями, вы не сможете уследить за адресами. На практике невозможно запомнить даже один адрес памяти.
Поэтому, чтобы запомнить адрес/место, присваиваем значение переменной; это послужит меткой, или идентификатором, ячейки памяти.
let number = 100;
Как видно на приведенном фрагмента кода, значение, хранящееся в ячейке памяти, — это число. Можно хранить и другие типы данных.
Типы данных
Типы данных — классификация данных, которая указывает компьютерной системе, как интерпретировать их значение. Числовой тип данных указывает компьютерной системе интерпретировать его значение как число, а строковый тип данных будет интерпретироваться как строка.
Переменная (область памяти) может содержать различные типы значений. В JavaScript есть динамические типы. Это означает, что переменная может содержать число, а позже быть переназначена строке.
В JavaScript есть примитивные и непримитивные (ссылочные) типы данных.
Примитивные типы данных хранят фактическое значение напрямую, что делает их эффективными с точки зрения памяти и ускоряет доступ к ним. К ним относятся number, string, bigint, boolean, null, undefined и symbol.
Непримитивные, или ссылочные, типы данных хранят адреса в памяти, что позволяет им ссылаться на сложные объекты и обмениваться данными между различными частями программы. Объекты in-built (встроенные) и user-defined (определяемые пользователем) являются ссылочными типами данных.
Массив — это объект, поэтому является непримитивным типом.
Значение и ссылка
Передача по значению
Примитивные типы данных хранят значение данных. Переменная (область памяти) содержит фактическое значение.
Примитивные типы хранятся в стеке (статическое распределение памяти) в порядке LIFO (last-in-first-out), то есть обратном порядку поступления. Значения имеют фиксированный размер и неизменяемы. Стек работает быстро, но ограничен в памяти.
При передаче значений JavaScript создает их копию.
let name1 = "Golden";
let name2 = name1; // name2 - это копия name1
name2 = "Anonymous"; // Не переопределяет name1
console.log(name1); // Golden
console.log(name2); // Anonymous
Итак, name1 — переменная, содержащая строковое значение «Golden». Вызов переменной — обращение к хранящемуся в ней значению. Если переменная присваивается другой переменной (как в примере выше), значение копируется из переменной name1 в новую переменную. Между двумя переменными нет никакой ссылки.

Передача по ссылке
Непримитивные (или ссылочные) типы хранятся иначе, чем примитивные, или типы значений. Когда создается объект, переменная является указателем на фактическое значение/элемент.
Указатель хранится в стековой памяти, а фактическое значение/элемент — в памяти кучи.
Куча — большой пул памяти, используемый для динамически выделяемых объектов, таких как массивы, где размер объекта может меняться с течением времени.
Ссылка/указатель в стеке указывает на значение в куче.
let data1 = {name: "Golden", role: "Backend Dev"};
let data2 = data1;
data2.role = "Janitor";
console.log(data1); // {name: "Golden", role: "Janitor"};
console.log(data2); // {name: "Golden", role: "Janitor"};

При передаче по ссылке обе переменные служат указателями на одну и ту же область памяти в куче, где находится реальное значение/элемент объекта.
data1 указывает на строку «d» в куче. Если data1 присвоить data2, то в отличие от примитивных типов копирования значений не произойдет. data2 будет указывать на ту же строку «d».
Это означает, что если свойство объекта в куче удаляется или изменяется в любой из переменных (указателей), то изменяется именно этот объект.
delete data1.name;
// то же самое, что
delete data2.name;
// ссылается на одно и то же свойство объекта
// Это означает, что к значению в куче памяти можно обратиться через любой из указателей (data1 или data2)
Это в значительной степени влияет на управление памятью. Если одна из переменных (указателей) больше не указывает на местоположение, другая все еще будет указывать на объект. Таким образом, эта область памяти в куче все еще занята.
Она помечается для сбора мусора только тогда, когда на нее больше не ведет ссылка, то есть и data1, и data2 больше не ссылаются на нее.
let data1 = {name: "Golden", role: "Backend Dev"};
let data2 = data1;
data1 = null;
console.log(data1) // null
console.log(data2) // {name: "Golden", role: "Backend Dev"};

Судя по диаграмме, data2 по-прежнему является указателем на строку «d» в куче памяти. Следовательно, значение в строке «d» все еще используется и не будет собрано в мусор. На это следует обратить внимание, чтобы в памяти не оставались неиспользуемые объекты.
Заключение
Объекты в JavaScript хранятся в куче, а переменные содержат ссылки на эти объекты в стеке. Такой подход, основанный на ссылках, позволяет динамически увеличивать и изменять объекты, но это также означает, что изменения в одной ссылке будут отражаться на всех ссылках. Понимание этого различия очень важно для того, чтобы избежать непредвиденных побочных эффектов при работе с объектами в JavaScript.
Читайте также:
- 7 каверзных вопросов для проверки знаний о JavaScript
- Цифры без диаграмм: хаки по JS-диаграммам
- JavaScript-анализ: выявление и устранение уязвимостей в веб-приложениях
Читайте нас в Telegram, VK и Дзен
Перевод статьи Golden Azubuike: Understanding JavaScript Data Types: Value vs. Reference