简体   繁体   English

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

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

I have a scenario where i need to copy the array of Objects(Main array) to another Temp array which should not have object reference basically if i make any modification to Main array it should not reflect in the Temp array so that i will preserve the copy independently.我有一个场景,我需要将对象数组(主数组)复制到另一个临时数组,如果我对主数组进行任何修改,它基本上不应该有对象引用,它不应该反映在临时数组中,以便我将保留独立复制。

I have used one of the code snippet from stack overflow this one does partially like if i delete all objects from the Main array the temp array still hold the value but when i do some modifications in main array and click cancel button iam removing all objects from the main array using array.Removeall();我使用了堆栈溢出中的代码片段之一,这个代码片段在一定程度上类似于如果我从主数组中删除所有对象,临时数组仍然保留该值但是当我在主数组中进行一些修改并单击取消按钮时,我会从中删除所有对象主数组使用 array.Removeall(); but the modification still exist in Temp array so which means that object having a reference.但修改仍然存在于 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;
}

my object structure is like我的对象结构就像

iam using knockout framework.我正在使用淘汰赛框架。

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

Let me understand: you don't want just have a new array, but you want to create a new instance for all objects are present in the array itself?让我明白:您不希望只拥有一个新数组,而是希望为数组本身中存在的所有对象创建一个新实例? So if you modify one of the objects in the temp array, that changes is not propagated to the main array?因此,如果您修改临时数组中的对象之一,该更改不会传播到主数组?

If it's the case, it depends by the values you're keeping in the main array.如果是这种情况,则取决于您在主数组中保留的值。 If these objects are simple objects, and they can be serialized in JSON, then the quickest way is:如果这些对象是简单的对象,并且可以用 JSON 序列化,那么最快的方法是:

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

If you have more complex objects (like instances created by some your own constructors, html nodes, etc) then you need an approach ad hoc.如果您有更复杂的对象(例如由您自己的构造函数、html 节点等创建的实例),那么您需要一种特别的方法。

Edit:编辑:

If you don't have any methods on your newObjectCreation , you could use JSON , however the constructor won't be the same.如果您的newObjectCreation上没有任何方法,则可以使用JSON ,但是构造函数不会相同。 Otherwise you have to do the copy manually:否则,您必须手动进行复制:

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

Lodash can be used for deep copying objects _.cloneDeep(value) Lodash 可用于深度复制对象_.cloneDeep(value)

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

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

For some other people with the same question.对于其他一些有同样问题的人。 You could also do it this way.你也可以这样做。
Using the new es6 features you could create a copy of an array (without reference) and a copy of every object without one level of references.使用新的es6 功能,您可以创建数组的副本(无引用)和每个对象的副本,而无需一级引用。

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

It's much more functional and idiomatic IMHO恕我直言,它更具功能性和惯用性

Note: Spread syntax effectively goes one level deep while copying an array.注意:在复制数组时, Spread 语法有效地深入一层 Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows ( it's the same with Object.assign() and spread syntax ).因此,它可能不适合复制多维数组,如下例所示(与 Object.assign() 和 spread 语法相同)。
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax更多信息: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

So basically if your objects doesn't have objects as properties.所以基本上如果你的对象没有对象作为属性。 This syntax is everything you need.这个语法是你需要的一切。 Unfortunately there is not "out of the box" deep clone feature on the spec but you can always use a library if that's what you need不幸的是,规范中没有“开箱即用”的深度克隆功能,但如果您需要,您可以随时使用库

Browser Compatibility Warning: I think it is part of the specification of Ecma now, but some browsers doesn't have full support of spread syntax jet.浏览器兼容性警告:我认为它现在是 Ecma 规范的一部分,但有些浏览器并不完全支持扩展语法 jet。 But using one of the popular transpilers out there you will be fine但是使用一种流行的转译器,你会没事的

To copy the values of an array without copying the reference of the array, you can simply do:要复制数组的值而不复制数组的引用,您可以简单地执行以下操作:

let tempArray = [...mainArray];

This is the recommended solution for AirBnb's JS Style Guide: https://github.com/airbnb/javascript#arrays这是 AirBnb 的 JS 风格指南的推荐解决方案: https : //github.com/airbnb/javascript#arrays

However, this will not create new referenes for the objects inside the array.但是,这不会为数组内的对象创建新的引用。 To create a new reference for the array and the objects inside, you can do:要为数组和其中的对象创建新引用,您可以执行以下操作:

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

So you want a deep copy without object reference?所以你想要一个没有对象引用的深拷贝? Sure, use .slice() .当然,使用.slice()

Example:例子:

var mainArr = [],
    tmpArr = []

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

PS: I don't think double-JSON parsing is performance wise . PS:我不认为双 JSON 解析是性能明智的

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

Use angular.copy .使用angular.copy But not for the whole array (because it would pass array items by reference), but iterate it and use angular.copy on its members.但不是针对整个数组(因为它会通过引用传递数组项),而是对其进行迭代并对其成员使用angular.copy

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

On nested array you can do:在嵌套数组上,您可以执行以下操作:

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

Use this function https://developer.mozilla.org/en-US/docs/Web/API/structuredClone使用此功能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