Копирование массива объектов в другой массив без ссылки на объект в javascript (Deep copy)

У меня есть сценарий, когда мне нужно скопировать массив объектов (Основной массив) в другой массив Temp, который не должен иметь ссылку на объект в основном, если я вношу какие-либо изменения в главный массив, который он не должен отражать в массиве Temp, так что я будет сохранять копию независимо.

Я использовал один из фрагментов кода из, который частично нравится, если я удаляю все объекты из массива Main, массив temp все еще удерживает значение, но когда я делаю некоторые изменения в основном массиве и нажмите кнопку отмены отмены iam все объекты из основного массива с использованием array.Removeall(); но модификация все еще существует в массиве Temp, поэтому это означает, что объект имеет ссылку.

clone: function (existingArray) {
  var newObj = (existingArray instanceof Array) ? [] : {};
  console.debug('newObj value is ' + newObj);
  for (i in existingArray) {
    console.debug('i value is' + i);
    if (i == 'clone') continue;
    console.debug('existingArray[i] value ' + existingArray[i]);
    if (existingArray[i] && typeof existingArray[i] == "object") {

      newObj[i] = this.clone(existingArray[i]);
    } else {
      console.debug('in else part ' + existingArray[i]);
      newObj[i] = existingArray[i];
    }
  }
  return newObj;
}

моя структура объекта похожа на

iam с использованием инфраструктуры нокаутов.

newObjectCreation = function (localIp, RemoteIp, areaId) {
  this.localIP = ko.observable(localIp);
  this.remoteIP = ko.observable(RemoteIp);
  this.areaId = ko.observable(areaId);
};

template.ProtocolArray.push(new newObjectCreation('', '', '')); // to create default row

Пожалуйста, помогите мне в этом отношении. Спасибо заранее.

Ответ 1

Позвольте мне понять: вам не нужен только новый массив, но вы хотите создать новый экземпляр для всех объектов, присутствующих в самом массиве? Итак, если вы изменяете один из объектов в массиве temp, эти изменения не распространяются на главный массив?

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

var tempArray = JSON.parse(JSON.stringify(mainArray));

Если у вас более сложные объекты (например, экземпляры, созданные некоторыми вашими конструкторами, узлами html и т.д.), вам нужен подход ad hoc.

Edit:

Если у вас нет методов на newObjectCreation, вы можете использовать JSON, однако конструктор не будет таким же. В противном случае вам нужно сделать копию вручную:

var tempArray = [];
for (var i = 0, item; item = mainArray[i++];) {
    tempArray[i] = new newObjectCreation(item.localIP, item.remoteIP, item.areaId);
}

Ответ 2

Lodash может использоваться для глубокого копирования объектов _.cloneDeep (значение)

var objects = [{ 'a': 1 }, { 'b': 2 }];

var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// → false

Ответ 3

Значит, вам нужна глубокая копия без ссылки на объект? Конечно, используйте .slice().

Пример:

var mainArr = [],
    tmpArr = []

tmpArr = mainArr.slice(0) // Shallow copy, no reference used.

PS: Я не думаю, что синтаксический анализ с двойным JSON показатель производительности.

Ответ 4

Для некоторых других людей с таким же вопросом. Вы также можете сделать это таким образом.
Используя новые функции es6, вы можете создать копию массива (без ссылки) и копию каждого объекта без одного уровня ссылок.

const copy = array.map(object => ({ ...object }))

Это намного функциональнее и идиоматичнее ИМХО

Примечание. Синтаксис Spread эффективно копируется на один уровень при копировании массива. Следовательно, он может быть неподходящим для копирования многомерных массивов, как показано в следующем примере (то же самое с Object.assign() и синтаксисом распространения).
Дополнительная информация: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

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

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

Ответ 5

Вы можете использовать Angular copy: angular.copy();

Ответ 6

Чтобы скопировать значения массива без копирования ссылки на массив, вы можете просто сделать:

let tempArray = [...mainArray];

Это рекомендуемое решение для AirBnb JS Style Guide: https://github.com/airbnb/javascript#arrays

Однако это не создаст новые ссылки для объектов внутри массива. Чтобы создать новую ссылку для массива и объектов внутри, вы можете сделать:

JSON.parse(JSON.stringify(mainArray));

Ответ 7

Используйте angular.copy. Но не для всего массива (потому что он будет передавать элементы массива по ссылке), но итерируйте его и используйте angular.copy для его членов.

var newArray = [];
for (var i = 0, item; item = mainArray[i];) {
    newArray[i] = angular.copy(item);
    i++;
}