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

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

Давайте разберем их на примерах. Рассмотрим эти два массива, их мы будем использовать дальше в наших примерах.

const array_simple = [1, 2, 3, 4, 5, 6];
const array_nested = [{
  color: 'red',
  model: '250 GT'
},
{
  color: 'black',
  model: '250 TR'
}];

1|Назначение деструктуризации: (неглубоко)

const arr_2 = [ ...array_simple]
console.log(arr_2);     // [1, 2, 3, 4, 5, 6]
arr_2[0] = 7;
console.log(arr_2);     // [7, 2, 3, 4, 5, 6]
console.log(array_simple);     // [1, 2, 3, 4, 5, 6]
// works absolutely fine

Но когда дело доходит до вложенного массива объектов/массивов. Это не работает должным образом. Проверь это-

const arr_2 = [  ...array_nested];
console.log(arr_2);

arr_2.push({color: "gray", model: "250 GTO"});

Добавление нового элемента не повлияет на исходный массив (попробуйте).
Исходный массив будет такой же длины, а arr_2 будет иметь длину 3. Хорошо, пока хорошо…
Но если мы изменить любой элемент в клонированном массиве, мы в конечном итоге испортим исходный массив.

arr_2[0].color = 'yellow';
console.log(arr_2);

Теперь попробуйте это. И увидеть волшебство 😃.

console.log(array_nested);

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

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

А как насчет других методов? Давайте обсудим их.

2 |Array.from : (мелко)

const new_array = Array.from(array_simple);
console.log(new_array);                 // [1, 2, 3, 4, 5, 6]

Он принимает массив, подобный или итерируемый объект (объекты, которые имеют свойство длины и индексированные элементы) в качестве первого параметра.

Второй необязательный параметр — это функция отображения, которая будет выполняться для каждого элемента массива.

В ES2015 синтаксис класса позволяет создавать подклассы как встроенных, так и определяемых пользователем классов; в результате статические методы, такие как Array.from, "наследуются" подклассами Array и создают новые экземпляры подкласса, а не Array.

3 | Array.map() : (мелко)

Этот метод создает новый массив в результате вызова предоставленной функции для каждого элемента массива.

const new_array = array_simple.map(x => x);
console.log(new_array);                 // [1, 2, 3, 4, 5, 6]

map не изменяет массив, для которого он вызывается (хотя callback при вызове может это сделать).

4 | Array.concat() : (мелко)

const new_array = old_array.concat([value1[, ...[valueN] ]])

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

const new_array = array_simple.concat();
console.log(new_array);                 // [1, 2, 3, 4, 5, 6]

5 | Array.slice() : (мелко)

Учитывая начальный и конечный (исключенный) индекс, он возвращает часть массива в новый массив (поверхностная копия).

Если мы опустим начальный и конечный индексы, он вернет весь массив.

const new_array = array_simple.slice();
console.log(new_array);                 // [1, 2, 3, 4, 5, 6]

Бонус:

6 | JSON.parse и JSON.stringify : (глубокое копирование)

JSON.stringify()преобразует объект в строку json.

JSON.parse(), тогда как преобразует строку json, анализируя ее в объект javascript.

Объединив эти два метода, мы можем глубоко клонировать вложенный объект.

const arr_2 = JSON.parse(JSON.stringify(array_nested));
arr_2[0].color = 'yellow';
console.log(array_nested);  // doesn't alter original array

Надеюсь, это помогло вам понять концепцию. 😄

Если вам понравился пост. Скажите своим коллегам, чтобы не допускали этих ошибок.

Использованная литература: