繁体   English   中英

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

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

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

我使用了堆栈溢出中的代码片段之一,这个代码片段在一定程度上类似于如果我从主数组中删除所有对象,临时数组仍然保留该值但是当我在主数组中进行一些修改并单击取消按钮时,我会从中删除所有对象主数组使用 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

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

如果是这种情况,则取决于您在主数组中保留的值。 如果这些对象是简单的对象,并且可以用 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);
}

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

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

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

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

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

恕我直言,它更具功能性和惯用性

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

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

浏览器兼容性警告:我认为它现在是 Ecma 规范的一部分,但有些浏览器并不完全支持扩展语法 jet。 但是使用一种流行的转译器,你会没事的

要复制数组的值而不复制数组的引用,您可以简单地执行以下操作:

let tempArray = [...mainArray];

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

但是,这不会为数组内的对象创建新的引用。 要为数组和其中的对象创建新引用,您可以执行以下操作:

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

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

例子:

var mainArr = [],
    tmpArr = []

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

PS:我不认为双 JSON 解析是性能明智的

您可以使用Angular 的副本angular.copy();

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

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

在嵌套数组上,您可以执行以下操作:

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

使用此功能https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

let deepClonedArrayOfObjects = structuredClone(originalArrayOfObjects);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM