在javascript中将对象数组复制到另一个没有对象引用的数组(深层复制)

时间:2012-03-27 08:27:04

标签: javascript

我有一个场景,我需要将对象数组(主数组)复制到另一个Temp数组,该数组不应该有对象引用,如果我对Main数组进行任何修改它不应该反映在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;
}

我的对象结构就像

我使用淘汰框架。

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

请在这方面帮助我。 提前谢谢。

8 个答案:

答案 0 :(得分:63)

让我明白一点:您不希望只有一个新数组,但是您想为数组本身中存在的所有对象创建一个新实例?因此,如果修改临时数组中的一个对象,那么这些更改不会传播到主数组?

如果是这种情况,则取决于您在主阵列中保留的值。如果这些对象是简单对象,并且可以使用JSON进行序列化,那么最快的方法是:

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

如果你有更复杂的对象(比如你自己的构造函数,html节点等创建的实例)那么你需要一个临时的方法。

编辑:

如果您的newObjectCreation上没有任何方法,则可以使用JSON,但构造函数不会相同。否则你必须手动复制:

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

答案 1 :(得分:8)

Lodash可用于深层复制对象_.cloneDeep(value)

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

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

答案 2 :(得分:6)

所以你想要一个没有对象引用的深层副本?当然,请使用.slice()

示例:

var mainArr = [],
    tmpArr = []

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

PS:我认为双JSON解析不是performance wise

答案 3 :(得分:3)

您可以使用Angular's copyangular.copy();

答案 4 :(得分:3)

要复制数组的值而不复制引用,您只需执行以下操作:

let tempArray = [...mainArray];

这是AirBnb JS风格指南的推荐解决方案:https://github.com/airbnb/javascript#arrays

答案 5 :(得分:3)

对于其他有相同问题的人。您也可以这样操作。
使用新的es6 features,您可以创建一个数组的副本(不带引用)和每个对象的一个​​副本,而不需要一个引用级别。

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

功能和惯用的恕我直言

  

注意:扩展语法在复制数组时有效地深入了。因此,可能不适合复制多维数组,如以下示例所示(与Object.assign()和散布语法相同)。
  更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

所以基本上,如果您的对象没有对象作为属性。此语法是您所需的一切。不幸的是,规范上没有“开箱即用”的深度克隆功能,但是如果您需要的话,您可以随时使用库

浏览器兼容性警告::我认为它现在是Ecma规范的一部分,但是某些浏览器还没有完整的support扩展语法喷射。但是,使用其中一种流行的编译器就可以了

答案 6 :(得分:0)

在嵌套数组上,您可以:

    const origin = [{ cat: 'Bengal', dog: 'Birman' }, { cat: 'Abyssinian', dog: 'Bombay' }];
    const clone = [];
    origin.forEach(v=> clone.push(Object.assign({}, v)));

答案 7 :(得分:-1)

使用angular.copy。但不是整个数组(因为它会通过引用传递数组项),而是迭代它并在其成员上使用angular.copy

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