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

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

Два больших типа данных

В JavaScript все значения делятся на две группы:

  1. Примитивы
  2. Объекты

Это деление принципиально важно.

Примитивные типы

К примитивам относятся:

  • number
  • string
  • boolean
  • null
  • undefined
  • symbol
  • bigint

Начнём с простого примера.

let a = 10;
let b = a;

b = 20;

console.log(a); // 10
console.log(b); // 20

Здесь:

  • в a лежит значение 10
  • в b копируется само значение
  • изменение b никак не влияет на a

Это поведение называется передача по значению.

Строки ведут себя так же

let firstName = 'Anna';
let secondName = firstName;

secondName = 'Maria';

console.log(firstName);  // Anna
console.log(secondName); // Maria

Строки — тоже примитивы.
Каждая переменная хранит собственное значение.

Объекты — другое поведение

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

const userA = {
  name: 'Alex'
};

const userB = userA;

userB.name = 'John';

console.log(userA.name); // John
console.log(userB.name); // John

Здесь происходит неочевидная для многих вещь:

  • в userA хранится не сам объект, а ссылка на него
  • в userB копируется эта же ссылка
  • обе переменные указывают на один и тот же объект

Это называется передача по ссылке.

Почему это важно понимать

На первый взгляд код выглядит безопасно:

function updateUser(user) {
  user.isActive = true;
}

const currentUser = { name: 'Alex' };
updateUser(currentUser);

console.log(currentUser.isActive); // true

Функция изменила объект, хотя формально ничего не возвращала.
Это нормальное поведение для объектов.

Примитивы так не работают

function updateCount(count) {
  count = count + 1;
}

let total = 5;
updateCount(total);

console.log(total); // 5

Здесь:

  • count — копия значения
  • изменение не влияет на исходную переменную

Почему это связано с замыканиями

Рассмотрим замыкание с примитивом:

function createCounter() {
  let count = 0;

  return function () {
    count++;
    return count;
  };
}

count:

  • примитив
  • но хранится внутри замыкания
  • живёт между вызовами функции

Теперь тот же принцип с объектом:

function createSettings() {
  const settings = { theme: 'dark' };

  return function () {
    settings.theme = 'light';
    return settings;
  };
}

Объект остаётся тем же самым, но его содержимое меняется.

Сравнение примитивов и объектов

console.log(5 === 5); // true
console.log('a' === 'a'); // true

С примитивами всё просто.

console.log({} === {}); // false

Каждый объект — это новая ссылка, даже если содержимое одинаковое.

Частая логическая ошибка

const a = { value: 1 };
const b = { value: 1 };

if (a === b) {
  console.log('Equal');
}

Этот код никогда не выполнится, потому что:

  • сравниваются ссылки
  • а не содержимое объектов

Как это влияет на копирование

const original = { name: 'Alex' };
const copy = original;

copy.name = 'John';

console.log(original.name); // John

Это не копия, а вторая ссылка.

Поверхностное копирование

const original = { name: 'Alex' };
const copy = { ...original };

copy.name = 'John';

console.log(original.name); // Alex

Теперь:

  • создан новый объект
  • верхний уровень скопирован

Но важно понимать ограничение.

Вложенные объекты

const user = {
  name: 'Alex',
  settings: {
    theme: 'dark'
  }
};

const copy = { ...user };
copy.settings.theme = 'light';

console.log(user.settings.theme); // light

Вложенный объект всё ещё общий.
Это поверхностное копирование, а не глубокое.

Практический вывод

На этом этапе важно чётко понимать:

  1. Примитивы копируются по значению
  2. Объекты передаются по ссылке
  3. Изменение объекта влияет на все ссылки
  4. Поверхностное копирование не изолирует вложенные структуры

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