我有两个对象的数组:
genericItems: Item[] = [];
backupData: Item[] = [];
我使用genericItems
数据填充我的html表格。该表是可修改的。有一个重置按钮可以撤消对backUpData
所做的所有更改。该数组由服务填充:
getGenericItems(selected: Item) {
this.itemService.getGenericItems(selected).subscribe(
result => {
this.genericItems = result;
});
this.backupData = this.genericItems.slice();
}
我的想法是,用户更改将反映在第一个阵列中,第二个阵列可用作重置操作的备份。我在这里面临的问题是当用户修改表(genericItems [])时,第二个数组backupData
也会被修改。这是怎么回事以及如何防止这种情况?
答案 0 :(得分:67)
试试这个:
克隆数组:
const myClonedArray = Object.assign([], myArray);
克隆对象:
const myClonedObject = Object.assign({}, myObject);
答案 1 :(得分:14)
在 Typescript 和ES6中,您可以使用扩展运算符:
const myClonedArray = [...myArray];
spread运算符也适用于对象,但只会做浅表复制(第一层子级)
const myShallowClonedObject = {...myObject};
要对对象进行深层复制,您需要一个外部库:
import * as cloneDeep from 'lodash/cloneDeep';
const deeplyClonedObject = cloneDeep(myObject);
答案 2 :(得分:8)
尝试以下代码:
this.cloneArray= [...this.OriginalArray]
答案 3 :(得分:2)
使用地图或其他类似解决方案无助于深深克隆对象数组。 无需添加新库即可轻松实现此目的的方法是先使用JSON.stringfy,然后使用JSON.parse。
在这种情况下,这应该可以工作:
this.backupData = JSON.parse(JSON.stringify( genericItems));
答案 4 :(得分:1)
试试这个:
[https://lodash.com/docs/4.17.4#clone][1]
var objects = [{ 'a': 1 }, { 'b': 2 }];
var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true
答案 5 :(得分:1)
我和primeNg DataTable有同样的问题。在尝试和哭泣之后,我已经使用此代码解决了问题。
private deepArrayCopy(arr: SelectItem[]): SelectItem[] {
const result: SelectItem[] = [];
if (!arr) {
return result;
}
const arrayLength = arr.length;
for (let i = 0; i <= arrayLength; i++) {
const item = arr[i];
if (item) {
result.push({ label: item.label, value: item.value });
}
}
return result;
}
用于初始化备份值
backupData = this.deepArrayCopy(genericItems);
重置更改
genericItems = this.deepArrayCopy(backupData);
灵丹妙药是使用{}
而不是调用构造函数来重新创建项目。
我已经尝试了new SelectItem(item.label, item.value)
无法正常工作。
答案 6 :(得分:1)
克隆数组的最简单方法是 backUpData = genericItems.concat();
这将为数组索引创建一个新内存
答案 7 :(得分:0)
看起来你可能犯了一个关于你在做数组副本的错误。看看下面我的解释和对代码的一些修改,它可以帮助您将数据重置为以前的状态。
在您的示例中,我可以看到以下内容:
我是否正确地认为你不希望第3点按顺序发生?
会更好吗
试试这个:
getGenericItems(selected: Item) {
this.itemService.getGenericItems(selected).subscribe(
result => {
// make a backup before you change the genericItems
this.backupData = this.genericItems.slice();
// now update genericItems with the results from your request
this.genericItems = result;
});
}
答案 8 :(得分:0)
代码中的以下行创建一个新数组,将genericItems
中的所有对象引用复制到该新数组中,并将其分配给backupData
:
this.backupData = this.genericItems.slice();
因此,虽然backupData
和genericItems
是不同的数组,但它们包含完全相同的对象引用。
您可以携带一个库来为您进行深度复制(如提到的@LatinWarrior)。
但如果Item
不是太复杂,也许你可以为它添加clone
方法来自己深度克隆对象:
class Item {
somePrimitiveType: string;
someRefType: any = { someProperty: 0 };
clone(): Item {
let clone = new Item();
// Assignment will copy primitive types
clone.somePrimitiveType = this.somePrimitiveType;
// Explicitly deep copy the reference types
clone.someRefType = {
someProperty: this.someRefType.someProperty
};
return clone;
}
}
然后在每个项目上调用clone()
:
this.backupData = this.genericItems.map(item => item.clone());
答案 9 :(得分:0)
看起来你想要的是对象的深层复制。为什么不使用Object.assign()
?不需要图书馆,它是一个单行代码:)
getGenericItems(selected: Item) {
this.itemService.getGenericItems(selected).subscribe(
result => {
this.genericItems = result;
this.backupDate = Object.assign({}, result);
//this.backupdate WILL NOT share the same memory locations as this.genericItems
//modifying this.genericItems WILL NOT modify this.backupdate
});
}
有关Object.assign()
的更多信息:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
答案 10 :(得分:0)
下面的代码可能会帮助您复制第一级对象
let original = [{ a: 1 }, {b:1}]
const copy = [ ...original ].map(item=>({...item}))
因此对于以下情况,值保持不变
copy[0].a = 23
console.log(original[0].a) //logs 1 -- value didn't change voila :)
此案件失败
let original = [{ a: {b:2} }, {b:1}]
const copy = [ ...original ].map(item=>({...item}))
copy[0].a.b = 23;
console.log(original[0].a) //logs 23 -- lost the original one :(
最终建议:
我想说的是lodash cloneDeep
API,它可以帮助您复制完全取消引用原始对象的对象内的对象。这可以作为单独的模块安装。
答案 11 :(得分:0)
您可以使用地图功能
toArray= fromArray.map(x => x);
答案 12 :(得分:0)
如果数组中的项目不是原始项目,则可以使用传播运算符来实现。
this.plansCopy = this.plans.map(obj => ({...obj}));
答案 13 :(得分:0)
以非常强大的方式克隆一个对象/数组(没有引用)
您可以使用 object
获取 array
/ @angular-devkit
的深层副本。
import { deepCopy } from '@angular-devkit/core/src/utils/object';
export class AppComponent {
object = { .... }
array = [ ... ]
constructor() {
const newObject = deepCopy(this.object);
const newArray = deepCopy(this.array);
}
}
答案 14 :(得分:-1)
$.extend(true, [], originalArray)
在数组的情况下,特别是在由对象组成的情况下
$.extend(true, {}, originalObject)
(如果有对象)