在Angular 2 + TypeScript中深层复制数组

Joe*_*ida 63 javascript typescript angular

我有一个输入的对象数组.让我们来称呼它content.

尝试深度复制时,它仍然具有对前一个数组的引用.

我需要复制该输入数组,并更改重复部分的一个属性.

很久以来我尝试了不成功的不同方法.

ES6方式:

public duplicateArray() {
  arr = [...this.content]
  arr.map((x) => {x.status = DEFAULT});
  return this.content.concat(arr);
}
Run Code Online (Sandbox Code Playgroud)

slice方式:

public duplicateArray() {
  arr = this.content.slice(0);
  arr.map((x) => {x.status = DEFAULT});
  return this.content.concat(arr);
}
Run Code Online (Sandbox Code Playgroud)

在这两个数组中,所有对象都有status: 'Default'.

在Angular 2中深度复制数组的最佳方法是什么?

YD1*_*D1m 106

检查一下:

  let cloned = source.map(x => Object.assign({}, x));
Run Code Online (Sandbox Code Playgroud)

  • 对于我来说,`source.map(x =>({... x}));最适合。 (6认同)
  • 如果我没有遗漏某些东西,这对字符串不起作用 - 当我尝试`var source = ["one","two","three"]; var cloned = source.map(x => Object.assign({},x));`我最终克隆为:`[{'0':'o','1':'n','2 ':'e'},{'0':'t','1':'w','2':'o'},{'0':'t','1':'h', '2':'r','3':'e','4':'e'}]` (3认同)
  • 与 Internet Explorer 不兼容 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign (2认同)

Cam*_*ert 39

简单:

let objCopy  = JSON.parse(JSON.stringify(obj));
Run Code Online (Sandbox Code Playgroud)

  • 这可能是一个好主意。但是有一个缺点:我不认为这会复制方法,前提是对象具有方法。 (2认同)
  • 如果对象具有函数属性或循环引用,则这将不起作用。 (2认同)

Joe*_*ida 13

我发现的唯一解决方案(几乎在发布问题后立即)是循环遍历数组并使用 Object.assign()

像这样:

public duplicateArray() {
  let arr = [];
  this.content.forEach((x) => {
    arr.push(Object.assign({}, x));
  })
  arr.map((x) => {x.status = DEFAULT});
  return this.content.concat(arr);
}
Run Code Online (Sandbox Code Playgroud)

我知道这不是最佳的.我想知道是否有更好的解决方案.


kab*_*bus 13

这对我有用:

this.listCopy = Object.assign([], this.list);
Run Code Online (Sandbox Code Playgroud)

  • 好的,我可能是错的.我测试了这段代码,它改变了另一个列表.可能是其他地方的原因.我目前无法访问计算机.稍后会尝试这个.我删除了之前的评论. (3认同)

小智 10

我在 Angular devkit 中发现了深度复制方法,这很正常,所以......也许你可以自己实现或使用它。

我更喜欢使用loadash,有很多对象和数组操作方法可以使用。

import { deepCopy } from '@angular-devkit/core/src/utils/object';

export class AppComponent {
  source = {
    ....
  }
  constructor() {
     const newObject = deepCopy(this.source);
  }
}
Run Code Online (Sandbox Code Playgroud)
Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.1000.8
@angular-devkit/build-angular     0.1000.8
@angular-devkit/build-optimizer   0.1000.8
@angular-devkit/build-webpack     0.1000.8
@angular-devkit/core              10.0.8
@angular-devkit/schematics        10.0.8
@angular/cli                      10.0.8
@ngtools/webpack                  10.0.8
@schematics/angular               10.0.8
@schematics/update                0.1000.8
rxjs                              6.5.5
typescript                        3.9.7
webpack                           4.43.0
Run Code Online (Sandbox Code Playgroud)


Bog*_*anC 9

深入复制具有嵌套对象的对象的一种干净方法是使用lodash的cloneDeep方法.

对于Angular,你可以这样做:

yarn add lodash或安装lodash npm install lodash.

在您的组件中,导入cloneDeep并使用它:

import * as cloneDeep from 'lodash/cloneDeep';
...
clonedObject = cloneDeep(originalObject);
Run Code Online (Sandbox Code Playgroud)

它只为您的构建添加了18kb,非常值得获益.

如果你需要更多地了解为什么使用lodash的cloneDeep,我也在这里写了一篇文章.


Ale*_*xei 6

这是Daria的建议(请参阅问题的注释),该建议从TypeScript 2.1开始工作,并且基本上从数组中克隆每个元素

this.clonedArray = theArray.map(e => ({ ... e }));
Run Code Online (Sandbox Code Playgroud)