深拷贝,孩子仍然参考原始对象

时间:2018-01-09 15:34:38

标签: javascript angular typescript clone deep-copy

我在对象(TypeScript,Angular4,Ionic3)上进行深度复制/克隆时遇到问题,该对象还包含其他对象的列表。每当我更改副本中的子对象时,原始对象也会受到更改的影响,反之亦然。我的REST API为我提供了以下JSON:

enter image description here

我有2种类型的对象在这种情况下是相关的,有更多,但它们不需要更改,因此我不包括那些:

import { Declaration } from './declaration.entity';

export class Period{
    constructor(
        public number: number,
        public status: string,
        public year: number,
        public month: number,
        public sum: number,
        public orderNumber: string,
        public userId: string,
        public submitDate: Date,
        public comment: string,
        public declarations: Declaration[]
    ){}
}

import { FileCustom } from './file.entity';
import { Period } from './period.entity';

export class Declaration{
    constructor(
        public id: number,
        public status: string,
        public name: string,
        public description: string,
        public amount: number,
        public date: Date,
        public period: Period,
        public userId: string,
        public files: FileCustom[],
        public comment: string   
    ){}
}

我想更改句点内的声明字段。我有一个名为期间(期间列表)的对象,我想克隆它。我需要时间不受影响。我看了一些其他主题和可能的解决方案并尝试了它们:

let cloned = this.periods.map(x => Object.assign({},x));

let cloned = this.periods.map(x => Object.assign([],x));

从这个主题:

Deep copy an array in Angular 2 + TypeScript

当我使用上述解决方案之一并更改副本中期间的注释字段时,原始文件保持不变。但是当我更改句点内的声明的注释字段时,原始文件也会更改,这是我想要阻止的。如何在没有任何孩子任何引用原件的情况下深度复制/克隆我的句点列表?

提前致谢。

2 个答案:

答案 0 :(得分:0)

如果对象原型不是问题且对象不包含函数,您可以JSON.stringify()并将其解析回新对象

let cloned = this.periods.map(x => JSON.parse(JSON.stringify(x)));

或者一次串联整个this.periods

let cloned = JSON.parse(JSON.stringify(this.periods))

答案 1 :(得分:0)

您可以使用lodash的cloneDeep函数来执行此操作,以避免来回对象进行字符串化。

对于您的Angular项目,您可以这样做:

使用lodashyarn add lodash

安装npm install lodash

由于我们将仅使用cloneDeep函数,为了减少包,我们只将函数导入组件,而不是整个lodash库:

import * as cloneDeep from 'lodash/cloneDeep';

我们将像这样使用它来深度复制对象:

copiedList = cloneDeep(originalList);

现在将某些内容更改为嵌套在副本中的对象不会更改原始对象。

此解决方案将为您的生产Angular捆绑添加18 kb。