web-dev-qa-db-ja.com

Angular 2 + TypeScriptの配列をディープコピーします。

入力であるオブジェクトの配列があります。それをcontentと呼びましょう。

ディープコピーしようとすると、以前の配列への参照がまだあります。

その入力配列を複製し、複製された部分の1つのプロパティを変更する必要があります。

長い間、私は成功しなかったさまざまな方法を試してきました。

ES6の方法:

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

sliceの方法:

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

両方とも、配列内のすべてのオブジェクトにstatus: 'Default'があります。

Angular 2の配列をディープコピーする最良の方法は何ですか?

52
Joel Almeida

これをチェックして:

  let cloned = source.map(x => Object.assign({}, x));
92
YD1m

シンプル:

let objCopy  = JSON.parse(JSON.stringify(obj));
34
Cameron Gilbert

これは私のために働いています:

this.listCopy = Object.assign([], this.list);
13
kabus

私が見つけた唯一の解決策(質問を投稿した直後)は、配列をループして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);
}

私はこれが最適ではないことを知っています。そして、もっと良い解決策があるのだろうか。

13
Joel Almeida

内部にネストされたオブジェクトを持つオブジェクトをディープコピーするクリーンな方法は、lodashのcloneDeepメソッドを使用することです。

Angularの場合、次のようにできます。

yarn add lodashまたはnpm install lodashを使用してlodashをインストールします。

コンポーネントでcloneDeepをインポートして使用します。

import * as cloneDeep from 'lodash/cloneDeep';
...
clonedObject = cloneDeep(originalObject);

ビルドに追加されるのはわずか18kbで、メリットがあります。

また、lodashのcloneDeepを使用する理由についてさらに詳しい情報が必要な場合は、 記事はこちら も書いています。

8
BogdanC

これはDariaの提案です(質問に関するコメントを参照)。これは TypeScript 2.1 から始まり、基本的には 配列から各要素を複製します

this.clonedArray = theArray.map(e => ({ ... e }));
2
Alexei

これは私自身のものです。複雑なケースでは機能しませんが、オブジェクトの単純な配列では十分です。

  deepClone(oldArray: Object[]) {
    let newArray: any = [];
    oldArray.forEach((item) => {
      newArray.Push(Object.assign({}, item));
    });
    return newArray;
  }
1
Alex Beugnet

別の方法として、GitHubプロジェクト ts-deepcopy を使用してnpmでも利用できます。オブジェクトを複製するか、以下のコードスニペットを含めることができます。

/**
 * Deep copy function for TypeScript.
 * @param T Generic type of target/copied value.
 * @param target Target value to be copied.
 * @see Source project, ts-deepcopy https://github.com/ykdr2017/ts-deepcopy
 * @see Code pen https://codepen.io/erikvullings/pen/ejyBYg
 */
export const deepCopy = <T>(target: T): T => {
  if (target === null) {
    return target;
  }
  if (target instanceof Date) {
    return new Date(target.getTime()) as any;
  }
  if (target instanceof Array) {
    const cp = [] as any[];
    (target as any[]).forEach((v) => { cp.Push(v); });
    return cp.map((n: any) => deepCopy<any>(n)) as any;
  }
  if (typeof target === 'object' && target !== {}) {
    const cp = { ...(target as { [key: string]: any }) } as { [key: string]: any };
    Object.keys(cp).forEach(k => {
      cp[k] = deepCopy<any>(cp[k]);
    });
    return cp as T;
  }
  return target;
};
0
Erik Vullings
let originalArray :string[]  = ['one', 'two', 'Sc-fi'];
let cloneArray :string[]  = originalArray.concat([]);
0
Adam111p