Как скопировать массив в JavaScript, чтобы изменения не задевали оригинал?
Присвоил const copy = arr, добавил в copy элемент через push — и оригинальный массив тоже изменился! Думал, что сделал копию. Как правильно скопировать массив, чтобы он был независимым?
2 ответа
Тут классическое непонимание: const copy = arr не копирует массив, а лишь даёт второе имя на тот же самый массив в памяти. Меняешь по любому имени — меняется один и тот же массив.
const arr = [1, 2, 3];
const copy = arr; // НЕ копия — та же ссылка
copy.push(4);
console.log(arr); // [1, 2, 3, 4] — оригинал тоже изменился!
Сделать настоящую (поверхностную) копию — несколько способов:
const arr = [1, 2, 3];
const c1 = [...arr]; // spread — самый частый
const c2 = arr.slice(); // slice без аргументов
const c3 = Array.from(arr); // Array.from
c1.push(4);
console.log(arr); // [1, 2, 3] — цел
console.log(c1); // [1, 2, 3, 4]
Все три создают новый массив, и теперь изменения независимы.
Важная оговорка — это поверхностная копия. Если в массиве лежат объекты, копируются ссылки на них, а не сами объекты:
const users = [{ name: 'Аня' }];
const copy = [...users];
copy[0].name = 'Боб';
console.log(users[0].name); // 'Боб' — вложенный объект общий!
Для глубокой копии (с вложенными объектами) бери structuredClone:
const deep = structuredClone(users);
deep[0].name = 'Вера';
console.log(users[0].name); // не изменился
Вывод: для плоского массива чисел/строк хватит [...arr]. Есть вложенные объекты и их тоже меняешь — structuredClone.
То же правило «присваивание — это ссылка, а не копия» работает и для объектов:
const a = { x: 1 };
const b = a;
b.x = 99;
console.log(a.x); // 99 — один объект
Копия объекта — через spread { ...a } или Object.assign({}, a). Запомни: в JS массивы и объекты передаются по ссылке, а числа/строки/булевы — по значению. Отсюда почти все «магические» изменения оригинала.