programing

Javascript/Typescript에서 어레이 복제

lastcode 2023. 4. 2. 10:36
반응형

Javascript/Typescript에서 어레이 복제

2개의 오브젝트가 배열되어 있습니다.

genericItems: Item[] = [];
backupData: Item[] = [];

을 HTML로 .genericItems데이터 테이블은 수정할 수 있습니다.은 리셋버튼을 하여 리셋된 대로 되돌릴 수 .backUpData 이.

getGenericItems(selected: Item) {
this.itemService.getGenericItems(selected).subscribe(
  result => {
     this.genericItems = result;
  });
     this.backupData = this.genericItems.slice();
  }

사용자 변경이 첫 번째 어레이에 반영되어 두 번째 어레이를 리셋 조작의 백업으로 사용할 수 있다는 것이 제 생각입니다.가 직면하고 있는 테이블)을 입니다.genericItems[]) 번째 배열 '2'backupData또한 수정됩니다.

어떻게 이런 일이 일어나고 있고 어떻게 예방할 수 있을까요?

개체 복제:

const myClonedObject = Object.assign({}, myObject);

어레이 복제:

  • 기본 유형 배열이 있는 경우 옵션 1:

const myClonedArray = Object.assign([], myArray);

  • 옵션 2 - 객체 배열이 있는 경우:
const myArray= [{ a: 'a', b: 'b' }, { a: 'c', b: 'd' }];
const myClonedArray = [];
myArray.forEach(val => myClonedArray.push(Object.assign({}, val)));

javascript에서 어레이와 오브젝트를 복제하는 구문은 다릅니다.조만간 모든 사람이 그 차이를 힘들게 알게 되고 결국 여기에 오게 된다.

TypescriptES6에서 배열 및 개체에 대해 확산 연산자를 사용할 수 있습니다.

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.

오브젝트를 상세하게 복사하려면 외부 라이브러리가 필요합니다.

import {cloneDeep} from 'lodash';
const myClonedArray = cloneDeep(myArray);     // This works for [{a:1}, {b:2}]

분산 연산자는 객체에서도 작동하지만 얕은 복사(자녀의 첫 번째 레이어)만 수행합니다.

const myShallowClonedObject = {...myObject};   // Will do a shallow copy
                                               // and cause you an un expected bug.

오브젝트를 상세하게 복사하려면 외부 라이브러리가 필요합니다.

 import {cloneDeep} from 'lodash';
 const deeplyClonedObject = cloneDeep(myObject);   // This works for [{a:{b:2}}]

맵이나 기타 유사한 솔루션을 사용하면 객체 배열을 깊이 복제하는 데 도움이 되지 않습니다.새 라이브러리를 추가하지 않고 이를 수행하는 더 쉬운 방법은 JSON.stringfy를 사용한 다음 JSON.parse를 사용하는 것입니다.

이 경우는, 다음과 같이 동작합니다.

this.backupData = JSON.parse(JSON.stringify(genericItems));
  • JS/TS의 마지막 버전을 사용할 때 lodash와 같은 큰 라이브러리를 1/2 기능에만 설치하는 것은 좋지 않습니다.앱의 퍼포먼스가 향상되어 장기적으로 라이브러리 업그레이드를 유지해야 합니다.https://bundlephobia.com/result?p=lodash @4.17.15 체크
  • 소형 Objet의 경우 lodash cloneDeep가 더 빠를 수 있지만, 대형/딥 객체의 경우 json 클론이 더 빠릅니다.따라서 이 경우 주저하지 말고 사용해야 합니다.https://www.measurethat.net/Benchmarks/Show/6039/0/lodash-clonedeep-vs-json-clone-larger-object infos https://v8.dev/cost/cost-of-script-2019#json을 확인하십시오.

  • 단, 소스 오브젝트는 JSON으로 변환할 수 있어야 합니다.

다음 코드를 시도합니다.

this.cloneArray= [...this.OriginalArray]

배열을 , "Da"에서 합니다.genericItems하여 할당하는 것입니다.backupData:

this.backupData = this.genericItems.slice();

★★★★★★★★★★★★★★★★★★★★★★★★★.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;
  }
}

전화 주세요.clone() 목목:

this.backupData = this.genericItems.map(item => item.clone());

어레이 복사 설명 - 깊이 및 깊이

아래 코드는 첫 번째 수준 개체를 복사하는 데 도움이 될 수 있습니다.

let original = [{ a: 1 }, {b:1}]
const copy = [ ...original ].map(item=>({...item}))

따라서 아래의 경우 값은 그대로 유지됩니다.

copy[0].a = 23
console.log(original[0].a) //logs 1 -- value didn't change voila :)

이 경우 실패

let original = [{ a: {b:2} }, {b:1}]
const copy = [ ...original ].map(item=>({...item}))
copy[0].a.b = 23;
console.log(original[0].a) //logs 23 -- lost the original one :(

lodash 개별 ES 모듈 시험 - cloneDeep:

go for lodash API(이것별도의 모듈로 설치할 수 있으며 트리쉐이킹용 코드 풋프린트를 줄임)를 사용하면 오브젝트 내의 오브젝트를 원래의 오브젝트로부터 완전히 디레퍼런스 할 수 있습니다.신뢰할 수 있는 또 하나의 옵션으로서JSON.stringify&JSON.parse을 사용하다

다음의 메뉴얼을 참조해 주세요. https://github.com/lodash/lodash

개별 패키지 : https://www.npmjs.com/package/lodash.clonedeep

지도 기능을 사용할 수 있습니다.

 toArray= fromArray.map(x => x);

매우 강력한 방법으로 오브젝트/어레이 클론 작성(참조 없음)

사진을 수 .objectarray를 사용합니다.@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);
  }
}

primeNg Data Table에도 같은 문제가 있습니다.노력 끝에 이 코드를 사용하여 문제를 해결했습니다.

private deepArrayCopy(arr: SelectItem[]): SelectItem[] {
    const result: SelectItem[] = [];
    if (!arr) {
      return result;
    }
    const arrayLength = arr.length;
    for (let i = 0; i <= arrayLength; i++) {
      const item = arr[i];
      if (item) {
        result.push({ label: item.label, value: item.value });
      }
    }
    return result;
  }

백업 값을 초기화하기 위해

backupData = this.deepArrayCopy(genericItems);

변경 리셋용

genericItems = this.deepArrayCopy(backupData);

입니다.{}이치노new SelectItem(item.label, item.value)과가없없 없없없다다

어레이를 복제하는 가장 쉬운 방법은

backUpData = genericItems.concat();

그러면 어레이 인덱스의 새 메모리가 생성됩니다.

배열의 항목이 원시 항목이 아닌 경우 분산 연산자를 사용하여 이를 수행할 수 있습니다.

this.plansCopy = this.plans.map(obj => ({...obj}));

완전한 답변 : https://stackoverflow.com/a/47776875/5775048

이것을 시험해 보세요.

[https://lodash.com/docs/4.17.4#clone][1]

var objects = [{ 'a': 1 }, { 'b': 2 }];

var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true

어레이의 카피를 어디서 하고 있는지 잘못 알고 있는 것 같습니다.아래의 설명과 코드를 약간 수정하면 데이터를 이전 상태로 리셋할 수 있습니다.

이 예에서는 다음과 같은 일이 일어나고 있습니다.

  • 범용 아이템을 취득하기 위한 요청을 하고 있습니다.
  • 데이터를 얻은 후 결과를 이 항목으로 설정합니다.generic Items
  • 그 직후에 backupData를 설정합니다.

세 번째 포인트가 그 순서로 발생하는 것을 원하지 않는다고 생각하는 것이 맞습니까?

이게 더 좋을까요?

  • 데이터 요청을 수행합니다.
  • 현재 이 항목의 백업 복사본을 만듭니다.generic Items
  • 그러면 요청의 결과로 genericItems를 설정합니다.

이것을 시험해 보세요.

getGenericItems(selected: Item) {
  this.itemService.getGenericItems(selected).subscribe(
    result => {
       // make a backup before you change the genericItems
       this.backupData = this.genericItems.slice();

       // now update genericItems with the results from your request
       this.genericItems = result;
    });
  }

원하는 것은 개체의 딥 카피인 것 같습니다.왜 사용하지 않는가?Object.assign()도서관은 필요 없고, 원라이너입니다:)

getGenericItems(selected: Item) {
    this.itemService.getGenericItems(selected).subscribe(
        result => {
            this.genericItems = result;
            this.backupDate = Object.assign({}, result); 
            //this.backupdate WILL NOT share the same memory locations as this.genericItems
            //modifying this.genericItems WILL NOT modify this.backupdate
        });
}

자세한 것은 이쪽Object.assign(): https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

어레이 레벨의 클로닝 솔루션은 기능하지 않고, 이 클론 유틸리티를 타이프 스크립트에 추가했습니다.이것은, 내 케이스에서 동작하는 보다 깊은 클론입니다.

export function cloneArray<T>(arr: T[]): T[] {
  return arr.map((x) => Object.assign({}, x))
}

즉, 배열을 함수에 전달하면[...arr]또는Object.assign([], arr)또는arr.splice()여전히 원래의 어레이를 변환하고 있었다.

이거 드셔보세요

const returnedTarget = Object.assign(target, source);

빈 어레이를 타겟에 전달합니다.

이런 식으로 복잡한 사물이 나에게 효과가 있는 경우

$.extend(true, [], originalArray)배열의 경우

$.extend(true, {}, originalObject)이의가 있는 경우

언급URL : https://stackoverflow.com/questions/44808882/cloning-an-array-in-javascript-typescript

반응형