Простое клонирование/копирование массива в JavaScript
Чтобы клонировать/копировать содержимое массива, все, что вам нужно сделать, это вызвать метод slice, передав 0 в качестве первого аргумента:
var clone = myArray.slice(0);
Код выше создает копию исходного массива; имейте в виду, если в вашем массиве существуют объекты — они хранятся как ссылки; т.е. код выше не делает “deep” клонирование содержимого массива.
Чтобы добавить копирование, как нативный метод к массивам, вы могли бы сделать что-то вроде этого:
Array.prototype.clone = function () < return this.slice(0); >;
Давайте напишем рекурсивную функцию, чтобы копировать массив, который потенциально может иметь вложенные объекты или массивы:
function arrayClone (arr) < var i, copy; if (Array.isArray(arr)) < copy = arr.slice(0); for (i = 0; i < copy.length; i++) < copy[i] = arrayClone(copy[i]); >return copy; > else if (typeof arr === 'object') < throw 'Cannot clone array containing an object!'; >else < return arr; >>
Если вы используете Underscore – можете сделать это еще короче:
function arrayClone (arr) < if (_.isArray(arr)) < return _.map(arr, arrayClone); >else if (typeof arr === 'object') < throw 'Cannot clone array containing an object!'; >else < return arr; >>
С версии ECMAScript 2015 был введен метод Object.assign(), с его помощью глубокое клонирование можно реализовать еще проще:
var clone = Object.assign([], myArray);
Заключение
Если вам нужно глубокое копирование произвольно-вложенных объектов и/или массивов, крошечный node-clone прекрасно с этим справиться. Он будет правильно обрабатывать даже копирование объектов с циклическими ссылками!
Источники
- Clone Arrays with JavaScript
- How to Clone a (Nested) Array in Javascript
Копирование массивов
В javascript нельзя скопировать массив просто присвоив переменную с массивом другой переменной, т.к. в результате мы получим две переменные, ссылающиеся на один и тот же массив. При изменении одной переменной будет изменяться и значение другой, т.к. обе ссылаются на одно и тоже место в памяти.
// две переменные ссылаются на один массив
var a = ["one", "two"];
var b = a;
b.pop();
console.log(a); //["one"]
console.log(b); //["one"]
Копировать массивы один в другой можно следующим образом
var copyArray = oldArray.slice();
// slice возвращает массив значений начиная с указанного индекса.
// без аргументов с 0-индекса
var copyArray = [].concat(oldArray);
// создаем пустой массив и объединяем со старым.
// или так
var copyArray = oldArray.concat();
Как скопировать массив js
У нас есть массив строк arr . Нужно получить отсортированную копию, но оставить arr неизменённым.
Создайте функцию copySorted(arr) , которая будет возвращать такую копию.
let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); alert( sorted ); // CSS, HTML, JavaScript alert( arr ); // HTML, JavaScript, CSS (без изменений)
Для копирования массива используем slice() и тут же – сортировку:
function copySorted(arr) < return arr.slice().sort(); >let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); alert( sorted ); alert( arr );
Создать независимую копию JavaScript массива :: Хранитель заметок
В JavaScript все присваивания объектов реализуются через передачу ссылок на них.
var oldArray = ["a", "b", "c"]; var newArray = oldArray;
Хоть мы и получили две разные переменные, но тем не менее они обе ссылаются на один и тот же объект массива. Если сейчас в одном массиве произвести какие-либо манипуляции с элементами, то аналогичные изменения можно будет увидеть и в другом.
Если вы хотите сделать независимую копию массива, то нужно использовать метод slice без аргументов.
var oldArray = ["a", "b", "c"]; var newArray = oldArray.slice();
Массивы oldArray и newArray будут состоять из одних и тех же элементов, но фактически это будут разные объекты.
Важно запомнить, что если массив состоит из сущностей Array или Object, то они по прежнему будут ссылаться на родительские объекты.
Ещё заметки со схожей тематикой
- Разная композиция функций
- Размер объекта в памяти
- Получение текущего состояние коллекции MongoDB в виде набора обновлений
Категории
Коментарии к заметке
Alexander , 07 июл 2011
slice реально очень хорошо помагает если надо скопировать массива. При этом, если измениь первый массив, то второй останется без изменений.
Дима , 08 окт 2015
Спасибо 🙂 Помогло
Елизарий , 18 апр 2016
Спасибо, искал долго, было много всего не по теме, а у вас сразу за пол странички все объяснили. Спасибо большое!
Илья , 15 сен 2016
Спасибо огромное, очень помогло с решением одной проблемы!!
Daddar , 12 окт 2016
атлант , 06 дек 2016
хорошо , ну а как все таки быть если в массиве сущности Обекты?
Владимир Кузнецов , 07 дек 2016
Атлант, тогда у этой задачи нет универсального решения. Объекты можно «клонировать» с помощью метода Object.assign() (описание Object.assign() на MDN).
var target = Object.assign(<>, source);
Но у этого метода как и slice() та же проблема — копируются только ссылки на вложенные объекты и массивы. Чтобы сделать глубокую копию всех данных, вам нужно рекурсивно вызывать соответствующие методы клонирования. В некоторых JS-библиотеках эти алгоритмы уже реализованы. Можете воспользоваться cloneDeep из библиотеки Lodash. А универсального решения задачи тут нет из-за того, что в ваших массивах и объектах могут храниться такие значения, для которых сложно или даже невозможно создать независимую копию, например, функции, DOM-узлы или объекты WeakMap.
arg , 24 авг 2017
Илья , 22 сен 2017
Способ, который работает и в случае, когда в массиве есть массивы или объекты:
var newArray = JSON.parse(JSON.stringify(oldArray))
Владимир Кузнецов , 22 сен 2017
Способ работающий, но очень медленный. Я бы не стал его использовать в проектах.
Илья , 26 мар 2018
Чуть мозг не поломал, пока не понял, что ссылки на объекты у скопированного массива действительно остаются прежними, спасибо за этот комментарий.
© 2009–2023 Владимир Кузнецов.
Все права защищены и принадлежат их владельцам.
Копирование материалов данного блога допускается только с разрешения автора.
