簡體   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