Примитивные и ссылочные значения в JavaScript

В этом руководстве вы узнаете о двух разных типах значений в JavaScript, включая примитивные и ссылочные значения.

JavaScript имеет два разных типа значений:

  1. Примитивные значения;
  2. Ссылочные значения.

Примитивные значения — это атомарные фрагменты данных, а ссылочные значения — это объекты, которые могут состоять из нескольких значений.

Стек и куча памяти

Когда вы объявляете переменные, механизм JavaScript выделяет для них память в двух местах памяти: в стеке и в куче.

Статические данные — это данные, размер которых фиксируется во время компиляции. Статические данные включают в себя:

  • Примитивные значения (null, undefined, boolean, number, string, symbol и BigInt)
  • Ссылочные значения, которые относятся к объектам.

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

Например, в следующем примере объявляются две переменные и инициализируются их значения буквальной строкой и числом:

let name = 'John'; 
let age = 25;

Поскольку name и age являются примитивными значениями, движок JavaScript сохраняет эти переменные в стеке, как показано на следующем рисунке:

Сохранение переменных в стеке

Обратите внимание, что строки являются объектами во многих языках программирования, включая Java и C#. Однако строки являются примитивными значениями в JavaScript.

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

В следующем примере определяются переменные name, age и person :

let name = 'John'; 
let age = 25; 
let person = { 
 name: 'John', 
 age: 25, 
};

Внутри движок JavaScript выделяет память, как показано на следующем рисунке:

Выделение памяти

На этом рисунке JavaScript выделяет память в стеке для трех переменных name, age и person.

Движок JavaScript создает новый объект в куче памяти. Кроме того, он связывает переменную person в памяти стека с объектом в памяти кучи.

По этой причине мы говорим, что переменная person является ссылкой на объект.

Динамические свойства

Ссылочное значение позволяет добавлять, изменять или удалять свойства в любое время. Например:

let person = { 
 name: 'John', 
 age: 25, 
}; 

// add the ssn property 
person.ssn = '123-45-6789'; 

// change the name 
person.name = 'John Doe'; 

// delete the age property 
delete person.age; 

console.log(person);

Выход:

{ name: 'John Doe', ssn: '123-45-6789' }

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

JavaScript позволяет добавлять свойство к примитивному значению. Однако никакого эффекта это не даст. Например:

let name = 'John'; 
name.alias = 'Knight'; 

console.log(name.alias); // undefined

Выход:

undefined

В этом примере мы добавляем свойство alias к примитивному значению name. Но когда мы обращаемся к свойству alias через примитивное значение name, оно возвращает undefined.

Копирование значений

Когда вы присваиваете примитивное значение одной переменной другой, механизм JavaScript создает копию этого значения и присваивает его переменной. Например:

let age = 25; 
let newAge = age;

В этом примере:

  • Во-первых, объявите новую переменную age и инициализируйте ее значение 25.
  • Во-вторых, объявите еще одну переменную newAge и присвойте age переменной newAge.

В фоновом режиме механизм JavaScript создает копию примитивного значения 25 и присваивает его переменной newAge.

На следующем рисунке показана память стека после присваивания:

Память стека

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

Например:

let age = 25; 
let newAge = age; 
newAge = newAge + 1; 

console.log(age, newAge);

Изменение переменной не влияет на другую

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

Например:

let person = { 
 name: 'John', 
 age: 25, 
}; 
let member = person; 

member.age = 26; 

console.log(person); 
console.log(member);

Как это работает.

Во-первых, объявите переменную person и инициализируйте ее значение с помощью объекта с двумя свойствами: name и age.

Во-вторых, назначьте переменную person переменной- member. В памяти обе переменные ссылаются на один и тот же объект, как показано на следующем рисунке:

Ссылка на один объект

В-третьих, измените свойство age объекта с помощью переменной- member :

Изменение свойства объекта

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

Заключение

  • Javascript имеет два типа значений: примитивные и ссылочные.
  • Вы можете добавлять, изменять или удалять свойства ссылочного значения, но не можете делать это с примитивным значением.
  • При копировании примитивного значения из одной переменной в другую создается отдельная копия значения. Это говорит о том, что изменение значения одной переменной не влияет на другую.
  • Копирование ссылки из одной переменной в другую создает ссылку, так что две переменные ссылаются на один и тот же объект. Это означает, что изменение объекта через одну переменную отражается в другой переменной.
Рейтинг
( Пока оценок нет )
Александр Русаков / автор статьи
Программист, разработчик, 12 лет опыта работы в крупных компаниях. Быстро освоил typescript, делюсь своими знаниями на страницах этого сайта.
Загрузка ...
JavaScript и TypeScript