[javascript] Javascript에서 객체 배열을 어떻게 복제합니까?

… 각 객체에는 동일한 배열 내의 다른 객체에 대한 참조가 있습니까?

내가 처음이 문제를 생각해 냈을 때

var clonedNodesArray = nodesArray.clone()

존재하고 자바 스크립트에서 객체를 복제하는 방법에 대한 정보를 검색했습니다. 나는 StackOverflow에 관한 질문 을 찾았으며 (매우 동일한 @JohnResig에 의해 답변 됨) jQuery를 사용하면 할 수 있다고 지적했습니다.

var clonedNodesArray = jQuery.extend({}, nodesArray);

객체를 복제합니다. 나는 이것을 시도했지만, 이것은 배열에있는 객체의 참조 만 복사합니다. 만약 내가

nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"

nodesArray [0] 및 clonedNodesArray [0]의 값이 모두 “green”으로 나타납니다. 그런 다음 시도했습니다

var clonedNodesArray = jQuery.extend(true, {}, nodesArray);

깊게 객체를 복사하지만 Firebug와 Opera Dragonfly에서 각각 ” 너무 많은 재귀 “와 ” 제어 스택 오버플로 “메시지를 받았습니다.

어떻게 하시겠습니까? 이조 차도해서는 안되는 일입니까? Javascript에서 재사용 가능한 방법이 있습니까?



답변

얕은 복사본의 문제는 모든 개체가 복제되지 않는다는 것입니다. 각 객체에 대한 참조는 각 배열에서 고유하지만 궁극적으로 객체를 가져 오면 이전과 동일한 객체를 처리하게됩니다. 복제 방법에는 아무런 문제가 없습니다. Array.slice ()를 사용하여 동일한 결과가 발생합니다.

딥 카피에 문제가있는 이유는 순환 객체 참조로 끝나기 때문입니다. 딥은 가능한 한 깊게 진행되며 원이 있으면 브라우저가 사라질 때까지 계속 무한대로 진행됩니다.

데이터 구조를 유향 비순환 그래프로 표현할 수 없다면, 심층 복제를위한 다목적 방법을 찾을 수 있을지 모르겠습니다. 순환 그래프는 많은 까다로운 코너 사례를 제공하며 일반적인 작업이 아니기 때문에 모든 사람이 완전한 솔루션을 작성했다고 의심합니다. 이 페이지에서이 문제에 대한 좋은 의견을 찾았습니다 .

순환 참조가있는 객체 배열의 깊은 사본이 필요한 경우 다중 데이터 복제와 같이 특수한 데이터 구조를 처리하기 위해 고유 한 방법을 코딩해야한다고 생각합니다.

  1. 첫 번째 라운드에서는 배열의 다른 객체를 참조하지 않는 모든 객체를 복제합니다. 각 객체의 원점을 추적합니다.
  2. 두 번째 라운드에서 객체를 서로 연결하십시오.

답변

객체에 JSON 직렬화 가능 콘텐츠 (함수, 아니오 Number.POSITIVE_INFINITY등)가 포함되어 있으면 배열이나 객체를 복제하기 위해 루프가 필요하지 않습니다. 다음은 순수한 바닐라 단선 솔루션입니다.

var clonedArray = JSON.parse(JSON.stringify(nodesArray))

아래 주석을 요약하면이 방법의 주요 장점은 배열 자체뿐만 아니라 배열의 내용도 복제한다는 것입니다. 주요 단점은 JSON 직렬화 가능 콘텐츠에 대한 작업의 한계이며 성능입니다 ( slice기반 접근 방식 보다 훨씬 나쁩니다 ).


답변

Object.assign을 사용 하여 객체 배열 복제를 해결했습니다.

const newArray = myArray.map(a => Object.assign({}, a));

스프레드 구문으로 더 짧거나

const newArray = myArray.map(a => ({...a}));


답변

얕은 사본 만 있으면 정말 쉬운 방법은 다음과 같습니다.

new_array = old_array.slice(0);


답변

이 복제를 수행하는 가장 좋은 방법은 다음과 같습니다.

사용하여 ... ES6 확산 연산자를.

가장 간단한 예는 다음과 같습니다.

var clonedObjArray = [...oldObjArray];

이런 식으로 배열을 개별 값으로 분산시키고 [] 연산자를 사용하여 새 배열에 넣습니다.

작동 방식을 보여주는 더 긴 예는 다음과 같습니다.

let objArray = [ {a:1} , {b:2} ];

let refArray = objArray; // this will just point to the objArray
let clonedArray = [...objArray]; // will clone the array

console.log( "before:" );
console.log( "obj array" , objArray );
console.log( "ref array" , refArray );
console.log( "cloned array" , clonedArray );

objArray[0] = {c:3};

console.log( "after:" );
console.log( "obj array" , objArray ); // [ {c:3} , {b:2} ]
console.log( "ref array" , refArray ); // [ {c:3} , {b:2} ]
console.log( "cloned array" , clonedArray ); // [ {a:1} , {b:2} ]


답변

이것은 나를 위해 작동합니다 :

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend({}, obj);
                  });

그리고 배열에 객체의 깊은 사본이 필요한 경우 :

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend(true, {}, obj);
                  });


답변

$.evalJSON($.toJSON(origArray));