Aru*_*run 49 arrays typescript angular
我有两个对象的数组:
genericItems: Item[] = [];
backupData: Item[] = [];
Run Code Online (Sandbox Code Playgroud)
我用genericItems数据填充我的html表.该表是可修改的.有一个重置按钮可以撤消所有已完成的更改backUpData.此数组由服务填充:
getGenericItems(selected: Item) {
this.itemService.getGenericItems(selected).subscribe(
result => {
this.genericItems = result;
});
this.backupData = this.genericItems.slice();
}
Run Code Online (Sandbox Code Playgroud)
我的想法是,用户更改将反映在第一个阵列中,第二个阵列可用作重置操作的备份.我在这里面临的问题是当用户修改表(genericItems [])时,第二个数组genericItems[])也会被修改.这是怎么回事以及如何防止这种情况发生的?
aba*_*het 102
试试这个 :
克隆数组:
const myClonedArray = Object.assign([], myArray);
Run Code Online (Sandbox Code Playgroud)
克隆一个对象:
const myClonedObject = Object.assign({}, myObject);
Run Code Online (Sandbox Code Playgroud)
Dav*_*han 31
在Typescript和ES6中,您可以使用spread运算符:
const myClonedArray = [...myArray]; // This is ok for [1,2,'test','bla']
// But wont work for [{a:1}, {b:2}].
// A bug will occur when you
// modify the clone and you expect the
// original not to be modified.
// The solution is to do a deep copy
// when you are cloning an array of objects.
Run Code Online (Sandbox Code Playgroud)
spread操作符也适用于对象,但它只会执行浅层复制(第一层子项)
import * as cloneDeep from 'lodash/cloneDeep';
const myClonedArray = cloneDeep(myArray); // This works for [{a:1}, {b:2}]
Run Code Online (Sandbox Code Playgroud)
要执行对象的深层复制,您需要一个外部库:
const myShallowClonedObject = {...myObject}; // Will do a shallow copy
// and cause you an un expected bug.
Run Code Online (Sandbox Code Playgroud)
Gau*_*war 10
试试下面的代码:
this.cloneArray= [...this.OriginalArray]
Run Code Online (Sandbox Code Playgroud)
使用地图或其他类似解决方案无助于深深克隆对象数组。在不添加新库的情况下执行此操作的更简单方法是使用JSON.stringfy,然后使用JSON.parse。
在你的情况下,这应该工作:
this.backupData = JSON.parse(JSON.stringify(genericItems));
Run Code Online (Sandbox Code Playgroud)
对于较小的对象,cloneDeep可以更快,但是对于更大/更深的对象,json克隆可以更快。因此,在这种情况下,您应该毫不犹豫地使用它。检查 https://www.measurethat.net/Benchmarks/Show/6039/0/lodash-clonedeep-vs-json-clone-larger-object和有关信息https://v8.dev/blog/cost-of-javascript -2019#json
不方便的是您的源对象必须可转换为JSON。
下面的代码可能会帮助您复制第一级对象
let original = [{ a: 1 }, {b:1}]
const copy = [ ...original ].map(item=>({...item}))
Run Code Online (Sandbox Code Playgroud)
所以对于下面的情况,值保持不变
copy[0].a = 23
console.log(original[0].a) //logs 1 -- value didn't change voila :)
Run Code Online (Sandbox Code Playgroud)
对于这种情况失败
let original = [{ a: {b:2} }, {b:1}]
const copy = [ ...original ].map(item=>({...item}))
copy[0].a.b = 23;
console.log(original[0].a) //logs {b: 23} -- lost the original one :(
Run Code Online (Sandbox Code Playgroud)
尝试 lodash 单独的 ES 模块 -cloneDeep:
我想说的是 lodash
cloneDeepAPI(它可以作为一个单独的模块安装,减少了 treeshaking 的代码占用),它可以帮助您复制对象内的对象,完全与原始对象解除引用。作为另一种选择,您也可以依靠JSON.stringify&JSON.parse方法来快速且高性能地取消引用。
请参阅文档: https: //github.com/lodash/lodash
单独包:https://www.npmjs.com/package/lodash.clonedeep
代码中的以下行创建一个新数组,将所有对象引用复制genericItems到该新数组中,并将其分配给backupData:
this.backupData = this.genericItems.slice();
Run Code Online (Sandbox Code Playgroud)
因此,虽然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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后调用clone()每个项目:
this.backupData = this.genericItems.map(item => item.clone());
Run Code Online (Sandbox Code Playgroud)
以非常强大的方式克隆对象/数组(没有引用)
您可以使用object/来获取/ 的深层复制。array@angular-devkit
import { deepCopy } from '@angular-devkit/core/src/utils/object';
export class AppComponent {
object = { .. some object data .. }
array = [ .. some list data .. ]
constructor() {
const newObject = deepCopy(this.object);
const newArray = deepCopy(this.array);
}
}
Run Code Online (Sandbox Code Playgroud)