关于javascript:深层复制,孩子们仍然参考原始对象

Deep copy, children still refer to original object

我在一个对象(typescript、angular4、ionic3)上有一个深度复制/克隆问题,该对象还包含其他对象的列表。每当我更改副本中的子对象时,原始对象也会受到更改的影响,反之亦然。我的RESTAPI返回以下JSON:

enter image description here

在本例中,我有两种类型的对象是相关的,有更多的对象,但它们不需要更改,因此我不包括这些对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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[]
    ){}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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  
    ){}
}

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

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

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

从本主题开始:

深度复制角度2+字体中的数组

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

事先谢谢。


您可以使用lodash的cloneDeep函数来完成这项工作,以避免来回串接对象。

对于角度项目,可以这样做:

yarn add lodashnpm install lodash安装lodash

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

埃多克斯1〔8〕

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

埃多克斯1〔9〕

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

此解决方案将为您的生产角束添加18kb。


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

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

或者一次串接整个this.periods

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