Копирование массива по значению
Описание проблемы:
Я столкнулся с проблемой при копировании массива в JavaScript. Когда я присваиваю один массив другому, оказывается, что оба массива ссылаются на одно и то же место в памяти. Вот пример кода:
var arr1 = ['a', 'b', 'c'];
var arr2 = arr1;
arr2.push('d'); // Теперь arr1 = ['a', 'b', 'c', 'd']
После выполнения этой операции я заметил, что при добавлении элемента в arr2
, изменился и arr1
, что совершенно не соответствует моим ожиданиям.
Как я могу сделать так, чтобы arr2
был независимой копией arr1
, чтобы изменения в одном массиве не влияли на другой?
5 ответ(ов)
Вот как я это сделал после того, как попробовал множество подходов:
var newArray = JSON.parse(JSON.stringify(orgArray));
Этот код создаст новый глубокий клон, который не связан с оригинальным массивом (это не поверхностная копия).
Конечно, этот метод не клонирует события и функции, но в этом есть хорошее преимущество: вы можете сделать это всего в одну строку, и он может быть использован для любых типов объектов (массивов, строк, чисел и объектов ...).
Некоторые из упомянутых методов хорошо работают с простыми типами данных, такими как числа или строки, но когда массив содержит другие объекты, эти методы могут не сработать. При попытке передать объект из одного массива в другой, он передаётся по ссылке, а не как отдельный объект.
Чтобы решить эту проблему, можно добавить следующий код в ваш JavaScript-файл:
Object.prototype.clone = function() {
var newObj = (this instanceof Array) ? [] : {};
for (i in this) {
if (i == 'clone')
continue;
if (this[i] && typeof this[i] == "object") {
newObj[i] = this[i].clone();
}
else
newObj[i] = this[i]
} return newObj;
};
После этого вы сможете использовать метод clone следующим образом:
var arr1 = ['val_1', 'val_2', 'val_3'];
var arr2 = arr1.clone();
Теперь arr2
будет независимой копией arr1
, и изменение одного из массивов не затронет другой.
В ES2015 (также известном как ES6) вы можете использовать оператор распространения (spread operator) для создания копии массива. В вашем примере:
var arr2 = [...arr1];
Эта строка кода создает новый массив arr2
, который является копией массива arr1
. Оператор ...
извлекает элементы из arr1
и помещает их в новый массив. Это позволяет избежать изменения оригинального массива при работе с его копией, что может быть полезно для сохранения неизменности данных.
Если вам нужно копировать массив, рекомендуется использовать именно этот метод, поскольку он является более современным и читаемым по сравнению с другими подходами, такими как Array.prototype.slice()
или цикл for
.
Когда вы используете метод array.slice() для копирования массивов, важно помнить, что в случае многомерных массивов подмассивы будут копироваться по ссылке. Это означает, что изменения, внесенные в подмассив, будут отражаться и в оригинальном массиве.
Чтобы избежать этого, вы можете пройтись по каждому подмассиву и использовать slice() для его индивидуального копирования. Вот пример:
var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice(); // Здесь создается поверхностная копия массива arr
arr2[0][1] = 55; // Изменяем значение в подмассиве arr2
console.log(arr2[0][1]); // Вывод: 55
console.log(arr[0][1]); // Вывод: 1 (оригинальный массив не изменился)
function arrCpy(arrSrc, arrDis) {
for (var elm in arrSrc) {
arrDis.push(arrSrc[elm].slice()); // Копируем каждый подмассив с помощью slice
}
}
var arr3 = [];
arrCpy(arr, arr3); // Копируем arr в arr3
arr3[1][1] = 77; // Изменяем значение в подмассиве arr3
console.log(arr3[1][1]); // Вывод: 77
console.log(arr[1][1]); // Вывод: 2 (оригинальный массив не изменился)
Также это относится и к массивам объектов: они будут копироваться по ссылке, и вам нужно будет копировать их вручную, если хотите избежать изменения оригинала.
Я бы предпочел использовать следующий способ:
JSON.parse(JSON.stringify(originalObject));
Этот метод позволяет создать глубокую копию объекта, что полезно, если вам нужно избежать изменений в оригинальном объекте. Однако имейте в виду, что этот способ не подходит для объектов с методами, функциями или сложными типами данных, такими как Date
, Map
, Set
и т. д. Если ваш объект содержит такие элементы, стоит рассмотреть альтернативные подходы, такие как использование библиотек для глубокого копирования (например, lodash) или ручное копирование с использованием рекурсии.
Как перемешать (сделать случайным) массив в JavaScript?
Как объединить два массива в JavaScript и удалить дубликаты?
Как очистить массив в JavaScript?
Как получить доступ к вложенным объектам, массивам или JSON и обработать их?
Как удалить все дубликаты из массива объектов?