Вы когда-нибудь сталкивались с ошибкой при клонировании массива? Не беспокойтесь .. Вы не будете повторять это снова.
Есть много способов клонировать массив. Но мы собираемся обсудить 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
Надеюсь, это помогло вам понять концепцию. 😄
Если вам понравился пост. Скажите своим коллегам, чтобы не допускали этих ошибок.
Использованная литература: