Что такое…

Что такое переменная — и почему копия списка меняется вместе с оригиналом

Иллюстрация: два ярлычка на верёвочках, привязанные к одному и тому же предмету

Почти в каждом объяснении переменную называют коробкой: положил значение — забрал значение. Удобно, понятно и работает ровно до первого настоящего бага.

Потому что вот это ломает всю картинку:

const a = [1, 2, 3];
const b = a;     // сделали "копию"
b.push(4);
console.log(a);  // [1, 2, 3, 4] — оригинал тоже изменился!

Ты трогал b. Сломался a. Если переменная — коробка, объяснить это невозможно.

Давай возьмём картинку поточнее. С ней этот баг становится очевидным.

Переменная — это бирка, а не коробка

Представь чемодан. На ручке — бирка с именем.

Значение — это чемодан. Переменная — бирка, привязанная к нему. Имя написано на бирке, вещи лежат в чемодане.

Вся разница вот в чём: к одному чемодану можно привязать две бирки. И тогда неважно, за какую ты тянешь — чемодан один и тот же.

Строчка const b = a; не копирует чемодан. Она вешает вторую бирку на тот же самый.

Поэтому b.push(4) кладёт вещь в общий чемодан, а a честно показывает, что там внутри. Никакой магии — просто бирок две, а чемодан один.

Почему иногда всё-таки копируется

Тут новичка ждёт вторая ловушка. Иногда = ведёт себя ровно так, как ждёшь:

let x = 5;
let y = x;
y = 10;
console.log(x);  // 5 — оригинал не тронут

Что случилось? Всё честно: числа, строки, true/falseпростые значения. Их не кладут в чемодан, их пишут прямо на бирке. Скопировал бирку — скопировал и значение.

А вот списки, объекты и всё составное — это чемоданы. На бирке пишут только «где он стоит».

Отсюда правило на каждый день:

  • число, строка, логическое= копирует значение, оригинал в безопасности;
  • список, объект, словарь= копирует только имя, чемодан остаётся общим.

Это устроено одинаково и в JavaScript, и в Python — двух языках, с которых чаще всего начинают. Так что выучил один раз — пригодится везде.

Как скопировать по-настоящему

Если нужна именно копия — её надо попросить явно.

В JavaScript:

const b = [...a];              // копия списка
const b = { ...obj };          // копия объекта
const b = structuredClone(a);  // копия вместе с вложенными

В Python:

b = a.copy()                 # копия списка
import copy
b = copy.deepcopy(a)         # копия вместе с вложенными

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

[...a] делает новый чемодан, но если внутри лежали другие чемоданы — в новый переложили их бирки, а не сами чемоданы. Верхний уровень отвязался, вложенные остались общими.

structuredClone и deepcopy копируют всё дерево целиком. Дороже по времени, зато честно и до конца.

Практическое правило: плоский список — хватит [...a]. Внутри объекты или вложенные списки — бери глубокую копию.

Где это выстрелит в коде от ИИ

Самое неприятное: такой баг не падает с ошибкой. Ничего не ломается, программа работает, данные просто тихо не те. Прочитать сообщение об ошибке тут не поможет — сообщения нет.

Выглядит это обычно так:

  • отредактировал одну запись в списке — «поехали» все;
  • сохранил черновик, изменил форму — черновик изменился вместе с ней;
  • отфильтровал массив «в копию» — и потерял оригинал.

Агент такое пишет регулярно, особенно когда правит код кусками и не видит, откуда пришёл список. Поэтому, когда просматриваешь код, написанный ИИ, держи глаз на строчках вида const copy = original;. Слово copy в имени переменной ничего не копирует — копирует только явный вызов.

Переменная и константа — в чём разница?

const запрещает перевязывать бирку на другой чемодан. Но содержимое чемодана менять не мешает: const a = [1,2]; a.push(3) — законно. Запрещено только a = [9]. Именно поэтому пример в начале статьи работает, несмотря на const.

Это то же самое, что переменные окружения?

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

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

Имя должно отвечать на вопрос «что внутри», а не «какого оно типа». userEmail лучше, чем str1. И не бойся длинных имён: код читают в разы чаще, чем пишут.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение
Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →