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

Copying of an array of objects to another Array without object reference in javascript(Deep copy)

我有一个场景,我需要将对象数组(主数组)复制到另一个临时数组,它基本上不应该有对象引用,如果我对主数组进行任何修改,它不应该反映在临时数组中,这样我就可以独立地保留副本。

我使用了堆栈溢出的一个代码段,这一部分类似于如果我从主数组中删除所有对象,临时数组仍然保留该值,但是当我在主数组中进行一些修改并单击"取消"按钮iam使用array.removeall()从主数组中删除所有对象;但是修改仍然存在于临时ar中。射线,这意味着物体有一个参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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使用淘汰框架。

1
2
3
4
5
6
7
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

请在这方面帮助我。事先谢谢。


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

如果是这样,它取决于您在主数组中保留的值。如果这些对象是简单的对象,并且可以在JSON中序列化,那么最快的方法是:

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

如果您有更复杂的对象(例如由您自己的构造函数、HTML节点等创建的实例),那么您需要一种特别的方法。

编辑:

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

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


lodash可用于深度复制对象uu.clonedeep(value)

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

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


所以你想要一个没有对象引用的深度复制?当然可以,使用.slice()

例子:

1
2
3
4
var mainArr = [],
    tmpArr = []

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

PS:我不认为双重JSON解析是性能方面的。


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

1
let tempArray = [...mainArray];

这是Airbnb JS风格指南的推荐解决方案:https://github.com/airbnb/javascript数组


你可以用安格尔的拷贝:angular.copy();


对于其他有同样问题的人。你也可以这样做。使用新的ES6功能,您可以创建一个数组的副本(不带引用)和一个不带一级引用的每个对象的副本。

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

它的功能性和惯用性要大得多。

Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign() and spread syntax).
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

所以基本上,如果你的对象没有对象作为属性。这个语法是您所需要的一切。不幸的是,规范中没有"开箱即用"的深度克隆功能,但是如果需要的话,您可以始终使用库。

浏览器兼容性警告:我认为它现在是ECMA规范的一部分,但有些浏览器不完全支持spread syntax jet。但是使用一个流行的蒸腾器你会很好的


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

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