Копирование массива в JavaScript
- Что значит скопировать массив
- Присваивание не копирует массив
- Копирование через spread
- Копирование через slice()
- Копирование через Array.from()
- Копия и изменение массива
- Поверхностная копия
- Что выбрать
- Итого
Копирование массива нужно, когда мы хотим получить новый массив с такими же элементами, но не менять исходный.
let numbers = [1, 2, 3];
let copy = [...numbers];
copy.push(4);
console.log(numbers); // [1, 2, 3]
console.log(copy); // [1, 2, 3, 4]
Что значит скопировать массив
Скопировать массив - значит создать новый массив и поместить в него элементы старого массива.
let fruits = ['apple', 'orange', 'banana'];
let fruitsCopy = [...fruits];
console.log(fruitsCopy); // ['apple', 'orange', 'banana']
После этого можно менять копию, не затрагивая исходный массив.
Присваивание не копирует массив
Если просто записать массив в другую переменную, копия не создается.
let fruits = ['apple', 'orange'];
let copy = fruits;
copy.push('banana');
console.log(copy); // ['apple', 'orange', 'banana']
console.log(fruits); // ['apple', 'orange', 'banana']
В переменной copy лежит ссылка на тот же массив. Поэтому изменение через copy видно и в fruits.
Это поведение связано с тем, что массивы в JavaScript относятся к ссылочным типам данных.
Копирование через spread
Самый частый способ скопировать массив - использовать spread-оператор ….
let fruits = ['apple', 'orange'];
let copy = [...fruits];
console.log(copy); // ['apple', 'orange']
Квадратные скобки создают новый массив, а …fruits раскладывает в него элементы старого массива.
Такой способ хорошо читается и часто используется в современном коде.
Копирование через slice()
Метод slice() без аргументов тоже создает копию массива.
let fruits = ['apple', 'orange'];
let copy = fruits.slice();
console.log(copy); // ['apple', 'orange']
slice() не меняет исходный массив. Он возвращает новый массив.
let fruits = ['apple', 'orange'];
let copy = fruits.slice();
copy.push('banana');
console.log(fruits); // ['apple', 'orange']
console.log(copy); // ['apple', 'orange', 'banana']
Копирование через Array.from()
Array.from() создает новый массив из переданного значения.
let fruits = ['apple', 'orange'];
let copy = Array.from(fruits);
console.log(copy); // ['apple', 'orange']
Для обычного копирования массива этот способ встречается реже, чем spread или slice(). Но он полезен, когда нужно получить массив из перебираемого значения.
let letters = Array.from('HTML');
console.log(letters); // ['H', 'T', 'M', 'L']
Копия и изменение массива
Копирование удобно, когда нужно получить измененный вариант массива и оставить исходный без изменений.
let numbers = [1, 2, 3];
let updatedNumbers = [...numbers, 4];
console.log(numbers); // [1, 2, 3]
console.log(updatedNumbers); // [1, 2, 3, 4]
Такой подход часто используют в интерфейсах: старые данные остаются как были, а для обновления создается новый массив.
Поверхностная копия
Spread, slice() и Array.from() создают поверхностную копию массива.
Если внутри массива лежат простые значения, например строки или числа, обычно этого достаточно.
let numbers = [1, 2, 3];
let copy = [...numbers];
copy[0] = 100;
console.log(numbers); // [1, 2, 3]
console.log(copy); // [100, 2, 3]
Но если внутри массива лежат объекты, копируются ссылки на эти объекты.
let users = [
{ name: 'Анна' },
{ name: 'Олег' },
];
let copy = [...users];
copy[0].name = 'Мария';
console.log(users[0].name); // Мария
Сам массив стал новым, но объекты внутри остались теми же. Если нужно менять объект внутри копии, его тоже нужно копировать отдельно.
let users = [
{ name: 'Анна' },
{ name: 'Олег' },
];
let copy = users.map((user) => ({ ...user }));
copy[0].name = 'Мария';
console.log(users[0].name); // Анна
console.log(copy[0].name); // Мария
Что выбрать
Для обычного копирования массива чаще всего используют spread.
let copy = [...items];
slice() тоже подходит, особенно если в проекте уже используют такой стиль.
let copy = items.slice();
Array.from() удобен, когда нужно создать массив из строки, коллекции DOM-элементов или другого перебираемого значения.
Итого
Чтобы получить независимый массив, нужно создать новую копию, а не просто присвоить массив другой переменной.
let copy = arrayне копирует массив, а записывает ссылку.[…array]- частый способ скопировать массив.array.slice()возвращает новый массив.Array.from(array)тоже создает новый массив.- Эти способы создают поверхностную копию.
- Если внутри массива объекты, их при необходимости копируют отдельно.