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에서 어레이와 오브젝트를 복제하는 구문은 다릅니다.조만간 모든 사람이 그 차이를 힘들게 알게 되고 결국 여기에 오게 된다.
Typescript 및 ES6에서 배열 및 개체에 대해 확산 연산자를 사용할 수 있습니다.
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);
매우 강력한 방법으로 오브젝트/어레이 클론 작성(참조 없음)
사진을 수 .object
array
를 사용합니다.@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
'programing' 카테고리의 다른 글
PHP - 기존 함수 재정의 (0) | 2023.04.02 |
---|---|
Jackson은 ISO8601 형식의 날짜 시간을 Java8 Instant로 역직렬화 (0) | 2023.04.02 |
Gradle을 사용한 Spring Boot Multi Module 프로젝트는 구축되지 않음 (0) | 2023.04.02 |
반응: 부모 구성 요소가 다시 렌더링될 때 어린이가 항상 다시 렌더링합니까? (0) | 2023.03.28 |
'합성 속성 @panelState를 찾았습니다.응용 프로그램에 "Browser Animations Module" 또는 "Noop Animations Module"을 포함하십시오.' (0) | 2023.03.28 |