21

Копирование массива по значению

17

Описание проблемы:

Я столкнулся с проблемой при копировании массива в JavaScript. Когда я присваиваю один массив другому, оказывается, что оба массива ссылаются на одно и то же место в памяти. Вот пример кода:

var arr1 = ['a', 'b', 'c'];
var arr2 = arr1;
arr2.push('d');  // Теперь arr1 = ['a', 'b', 'c', 'd']

После выполнения этой операции я заметил, что при добавлении элемента в arr2, изменился и arr1, что совершенно не соответствует моим ожиданиям.

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

5 ответ(ов)

0

Вот как я это сделал после того, как попробовал множество подходов:

var newArray = JSON.parse(JSON.stringify(orgArray));

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

Конечно, этот метод не клонирует события и функции, но в этом есть хорошее преимущество: вы можете сделать это всего в одну строку, и он может быть использован для любых типов объектов (массивов, строк, чисел и объектов ...).

0

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

Чтобы решить эту проблему, можно добавить следующий код в ваш 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, и изменение одного из массивов не затронет другой.

0

В ES2015 (также известном как ES6) вы можете использовать оператор распространения (spread operator) для создания копии массива. В вашем примере:

var arr2 = [...arr1];

Эта строка кода создает новый массив arr2, который является копией массива arr1. Оператор ... извлекает элементы из arr1 и помещает их в новый массив. Это позволяет избежать изменения оригинального массива при работе с его копией, что может быть полезно для сохранения неизменности данных.

Если вам нужно копировать массив, рекомендуется использовать именно этот метод, поскольку он является более современным и читаемым по сравнению с другими подходами, такими как Array.prototype.slice() или цикл for.

0

Когда вы используете метод 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 (оригинальный массив не изменился)

Также это относится и к массивам объектов: они будут копироваться по ссылке, и вам нужно будет копировать их вручную, если хотите избежать изменения оригинала.

0

Я бы предпочел использовать следующий способ:

JSON.parse(JSON.stringify(originalObject));

Этот метод позволяет создать глубокую копию объекта, что полезно, если вам нужно избежать изменений в оригинальном объекте. Однако имейте в виду, что этот способ не подходит для объектов с методами, функциями или сложными типами данных, такими как Date, Map, Set и т. д. Если ваш объект содержит такие элементы, стоит рассмотреть альтернативные подходы, такие как использование библиотек для глубокого копирования (например, lodash) или ручное копирование с использованием рекурсии.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь