Краткий обзор ценностей JS и ссылки

В этом блоге я расскажу о двух разных типах данных: примитивных и непримитивных.

Они представляют собой два разных способа хранения данных в памяти.

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

Что такое типы данных?

Если вы хоть немного разбираетесь в коде, вы должны знать, что существует множество различных «типов» данных.

Некоторые функции могут применяться только к определенному типу данных.

Например:

// The following is possible:
5 * 3 // 15
"ha" + "ppy" // "happy"
// The following is not possible:
"ben" * 2 // NaN You cannot multiply a string
"hope" - "o" // NaN You cannot subtract a string from another string

В то же время разные типы данных по-разному хранятся в памяти компьютера.

Примитивный против непримитивного

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

Примитивный

  1. Числа
  2. Струны
  3. Булевы
  4. неопределенный
  5. нулевой

Непримитивные (совместно именуемые Объектами)

  1. Объекты
  2. Массивы
  3. Функции

Эти две категории представляют два разных способа хранения этих типов данных в памяти. Примитивы хранятся по значению, а Непримитивы (объекты) хранятся по ссылке.

Давайте посмотрим на пример того, как хранятся примитивы:

let a = 5
let b = a
console.log(a) // 5
console.log(b) // 5
console.log(a === b) // true
a = 10
console.log(a) // 10
console.log(b) // 5
console.log(a === b) // false

Что здесь случилось?

Мы устанавливаем две разные переменные: a и b .

a было установлено равным 5.

b был установлен равным a.

Затем мы изменили значение a на 10.

Тем не менее, каким-то образом значение b все еще было 5!

Это потому, что примитивы хранятся по значению.

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

Вернемся к нашему примеру:

let a = 5
let b = a

Тип данных для a - это число, которое является примитивным типом данных. Его значение равно 5.

Тип данных для b также является числом. Имеет значение a.

Однако переменная b хранит не саму переменную a, а ее значение.

a имеет значение 5, поэтому b сохраняет 5 в своем адресе.

Позже, даже если мы решим изменить значение a, это не повлияет на значение, которое уже было сохранено внутри b.

Вот почему, когда мы сравниваем эти два сейчас, они больше не эквивалентны.

Теперь посмотрим на Непримитивы (объекты):

let a = [10]
let b = a
console.log(a === b) // true
a.push(10)
console.log(a) // [10, 10]
console.log(a === b) // true

Мы устанавливаем две разные переменные: a и b.

a был установлен равным массиву, содержащему одно значение: 10.

b был установлен равным a.

Сравнение a и b возвращает значение true.

Затем мы изменили данные внутри a.

Тем не менее, сравнивая две переменные еще раз, мы все равно возвращаем true.

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

Посмотрите на это с другой стороны:

let a = [10]
let b = a
// the variable a is referencing the address of the array object [10]
// the variable b is referencing the address of the variable a which is pointing to the address of [10]

По сути, мы всегда сохраняем указатели на адрес при работе с непримитивными типами данных.

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

let a = []
let b = a
let c = b
a.push(1)
console.log(a) // [1]
console.log(b) // [1]
console.log(c) // [1]
b.push(2)
console.log(a) // [1, 2]
console.log(b) // [1, 2]
console.log(c) // [1, 2]

Давайте посмотрим на это с другой стороны:

console.log([10] === [10])

Как вы думаете, что является результатом приведенной выше строки кода?

Думаю об этом….

Что именно мы сравниваем в этой строке кода?

Они указывают на один и тот же адрес?

Ответ?

Неверно!

Почему это так?

Находясь на поверхности, они оба содержат одно и то же значение, оба являются массивами, и оба содержат один элемент с равным значением (10).

Однако вы сравниваете не стоимость, а адреса.

[10] слева имеет другой адрес в памяти, чем [10] слева.

Оператор равенства (===) проверяет, указывают ли они на один и тот же адрес, поэтому результат ложный.

Заключение

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

В случае хранения примитивов эта переменная указывает на новый адрес для этого примитивного значения. При сохранении примитивного значения (даже если это просто переменная, для которой установлено значение), вы сохраняете само значение по новому адресу.

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