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


421

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

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

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에서 재사용 가능한 방법이 있습니까?

답변:


106

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

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

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

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

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

1
@PatrickdeKleijn 응답에 대한 고정 링크 : web.archive.org/web/20140222022056/http://my.opera.com/...
마이크 Szyndel

531

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

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

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


118
JSON 데이터에는 효과가 있지만 배열에 메소드가있는 함수 또는 객체 인스턴스가 포함되어 있으면 작별 인사를하십시오.
sp0rkyd0rky

12
Infinity 값을 포함하는 배열이있는 경우주의하십시오. 이 값은 없어집니다 (나중에 null 임). ( jsfiddle.net/klickagent/ehm4bd3s )
klickagent.ch

13
배열은 (심지어에만 프리미티브를 포함, 및 / 또는 자신 만 문자열 / 숫자 / 부울 프리미티브를 포함하는 개체하지 않는 한 이것은 단지 일반적으로 나쁜 방법입니다 nullundefinedJSON이를 지원하지 않기 때문에, 문제가 될 것입니다). 또한보다 효율적이고 효율적으로 작동하는 것보다 운영 효율성이 훨씬 낮습니다 old_array.slice(0);.
XML

2
배열의 객체에 DateTime이 있으면 DateTime 대신 문자열이 반환됩니다! new Date! == JSON.parse (JSON.stringify (new Date))
MarkosyanArtur

2
OP의 질문의 핵심 라인은 위의 대답이 완전히 무시합니다. ... 각 객체에는 동일한 배열 내의 다른 객체에 대한 참조가 있습니까?
XML

288

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

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

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

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

15
그러나 myArray에 많은 공룡이 포함 된 경우 newArray에는 많은 객체가 포함됩니다. 그것은 절름발이입니다, 당신은 동의하지 않습니까?
Matthew James Davis

3
가장 좋은 방법, 그것은 JSON.parse (JSON.stringify (nodesArray))로 손실 후 살아, 라텐 객체의 기능을 유지로
scipper

14
당신은 대체하여이 문제를 해결할 수 @MatthewJamesDavis {}와 함께 new Dinosaur().
Agargara

5
얕은 복사하지 딥 카피
술탄 빈 라덴

1
객체에 기본 속성 만 포함되어있는 경우 객체 배열에
유용

154

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

new_array = old_array.slice(0);

6
나는 당신이 통과해야한다고 생각하지 않습니다 0, 당신은 .slice()어쨌든 적어도 크롬에서 전화 할 수 있습니다
slf

112
이것은 실제로 작동하지 않습니까? 그것은 객체 배열을 복제하는 방법에 대한 대답이 아닙니다. 이것이 간단한 배열을 복제하는 솔루션입니다.
bozdoz

35
실제로 이것은 객체 배열에서는 작동하지 않습니다. 반환 된 배열 slice은 새로운 배열이지만 원래 배열 객체에 대한 참조를 포함합니다.
Sergio A.

4
이것은 "generics"int, string 등에 대해서만 작동하지만 객체 배열에는 작동하지 않습니다.
Stefan Michev

5
객체 배열의 경우 실제로 복제되지는 않으며 new_array로 업데이트하면 old_array도 업데이트됩니다.
Anas

44

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

사용하여 ... 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} ]


2
IE 11과 같은 오래된 브라우저에서는 작동하지 않는 현대적인 좋은 답변
Jealie

1
@Jealie KingpinEX가 es6을 Babel에 더 보편적으로 유용한 것으로 변환하는 사람들을 위해이 답변을 목표로하고 있다고 생각합니다.
루핀

61
이것은 배열의 각 객체가 아니라 배열을 깊게 복사합니다.
Toivo Säwén

31
@ ToivoSäwén이 말한 것을 추적하기 위해 배열의 객체를 깊게 복사하지는 않습니다. 여전히 원본 객체를 참조하므로 변경하면 원래 배열에도 영향을 미칩니다.
Joel Kinzel

3
프리미티브에만 작동합니다. 이것을 시도하십시오 : objArray [0] .a = 3; 그러면 객체의 참조가 clonedArray에서 동일하게 유지됩니다.
세르지오 코레아

25

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

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

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

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

1
이것은 작동하는 것처럼 보입니다. 광범위한 jQuery 사용을 피하려고 노력하고 있으므로 내 상황에서는 사용하지 않지만 for 루프 및 for ... in이 작동합니다.
bozdoz

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

2
당신은 사용해야합니다 JQuery와 JSON 플러그인이 사용하는 code.google.com/p/jquery-json을
wmitchell

32
JQ없이 (현대 브라우저에서는 양호) :JSON.parse(JSON.stringify(origArray));
forresto

이 의견이 유용하다는 것을 알았습니다. 구현에서 KnockoutJS 관찰 가능 속성이 적용된 객체 배열의 복사본을 만들어야했습니다. 사본에는 관찰 가능한 값이 아니라 값만 필요했습니다. JUST의 사본을 만들기 위해 JSON.parse (ko.toJSON (origArray)) 또는 ko.utils.parseJson (ko.toJSON (origArray))을 사용했습니다. 내 2 센트 만 내 솔루션에 도달하도록 도와 주셔서 감사합니다.
wavedrop

6
JSON.parse(JSON.stringify(origArray));확실히 가장 간단한 솔루션입니다.
yorkw

jQuery는 종종 불필요합니다. youmightnotneedjquery.com
ADJenks

9

은 이전 배열을 참조하지 않고 이전 배열에서 새 배열을 작성하고 맵 내에서 새 오브젝트를 작성하고 특성 (키)을 반복하고 이전 배열 오브젝트의 값을 코어 응답 특성을 새 오브젝트에 지정합니다.

이것은 정확히 동일한 객체 배열을 만듭니다.

let newArray = oldArray.map(a => {
               let newObject = {};
               Object.keys(a).forEach(propertyKey => {
                    newObject[propertyKey] = a[propertyKey];
               });
               return newObject ;
});

8

고통스러운 재귀를하지 않고 문제의 대상에 대한 모든 세부 사항을 알지 않고도이 작업을 수행하는 간단한 방법이있을 수 있습니다. jQuery를 사용하여 jQuery를 사용하여 객체를 JSON으로 변환 $.toJSON(myObjectArray)한 다음 JSON 문자열을 가져와 객체로 다시 평가하십시오. 밤! 완료했습니다! 문제 해결됨. :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));

21
일부 최신 브라우저에는 JSON 메소드가 내장되어 있으므로 JSON.parse (JSON.stringify (MY_ARRAY))이 더 빠릅니다. 좋은 제안.
Nicolas R

1
그리고 그들이 json2를 사용 하지 않으면 eval.
kamranicus

이것은 끔찍한 성능을 가지고 있지만 불행히도 내가 본 최고의 답변입니다 : /
Dvid Silva

사용자 데이터를 평가하지 마십시오. 바람직하게는 전혀 사용하지 마십시오 eval(). 보안 위험이 있습니다.
ADJenks

8

"Javascript에서 객체 배열 복제"문제에 대한 간단하고 명시적인 해결책이 없기 때문에이 질문에 대답하고 있습니다.

function deepCopy (arr) {
    var out = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        var item = arr[i];
        var obj = {};
        for (var k in item) {
            obj[k] = item[k];
        }
        out.push(obj);
    }
    return out;
}

// test case

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

var copy = deepCopy(original);

// change value in copy
copy[0]['a'] = 'not 1';

// original[0]['a'] still equals 1

이 솔루션은 배열 값을 반복 한 다음 객체 키를 반복하여 후자를 새 객체에 저장 한 다음 새 객체를 새 배열로 푸시합니다.

jsfiddle을 참조하십시오 . 참고 : 배열 내의 객체 에는 단순 .slice()하거나 [].concat()충분하지 않습니다 .


답변 주셔서 감사하지만 답변의 단점을 강조 표시해야합니다. 개체에 개체가 있으면 작동하지 않습니다. 그렇죠?
Harsh

얕은 사본을 만듭니다. 깊지 않음
sultan aslam

어딘가에 재귀를 추가해야합니다
DGoiko

6

JQuery extend가 제대로 작동하면 객체 대신 배열을 복제하도록 지정하면됩니다 ( extend 메소드의 매개 변수로 {} 대신 [] 참고 ).

var clonedNodesArray = jQuery.extend([], nodesArray);

2
흠, 당신이 이것을 하향 투표한다면, 왜 그렇게하는지에 대한 의견을 추가 할 수 있습니까? 아니면 먼저 코드를 사용 해보고 작동하는지 확인할 수 있습니까? 감사합니다;)
Stef

1
첫 번째 배열에서 객체를 변경하면 두 번째 배열의 객체가 수정되므로 괜찮습니다.
Spikolynn

6

이 방법은 매우 간단하며 원래 배열을 수정하지 않고 복제본을 수정할 수 있습니다.

// Original Array
let array = [{name: 'Rafael'}, {name: 'Matheus'}];

// Cloning Array
let clone = array.map(a => {return {...a}})

// Editing the cloned array
clone[1].name = 'Carlos';


console.log('array', array)
// [{name: 'Rafael'}, {name: 'Matheus'}]

console.log('clone', clone)
// [{name: 'Rafael'}, {name: 'Carlos'}]


1
이 깊은 두 가지 수준의 반면 얕은 복사 않습니다 [...oldArray]oldArray.slice(0)얕은을 한 수준의 깊이를 복사합니다. 따라서 이것은 매우 유용하지만 실제 전체 딥 클론은 아닙니다.
벤 휠러

진정한 딥 클론은 lodash.clonedeepnpm에서 사용 가능
계시

5

Daniel Lew가 언급했듯이 순환 그래프에는 몇 가지 문제가 있습니다. 이 문제가 발생하면 특별한 것을 추가하십시오.clone() 하면 문제가있는 객체에 방법을 하거나 이미 복사 한 객체를 기억합니다.

copyCount코드에서 복사 할 때마다 1 씩 증가 하는 변수 로 처리합니다. 더 낮은 물체copyCount현재 복사 프로세스보다 가 복사됩니다. 그렇지 않은 경우 이미 존재하는 사본을 참조해야합니다. 원본에서 사본으로 연결해야합니다.

여전히 문제가 하나 있습니다 : 메모리. 한 객체에서 다른 객체로이 참조가있는 경우 브라우저는 해당 객체가 항상 어딘가에서 참조되므로 해당 객체를 해제 할 수 없습니다. 모든 복사 참조를 Null로 설정하는 두 번째 단계를 거쳐야합니다. (이 작업을 수행 하면 두 번째 패스에서 값을 재설정 할 수 있으므로 copyCount부울 isCopied이 충분 하지 않아도됩니다 .)


4

Array.slice는 배열 또는 배열의 일부를 복사하는 데 사용할 수 있습니다 .. http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html 이것은 문자열 및 숫자와 함께 작동합니다. 한 배열은 다른 배열에 영향을 미치지 않지만 개체는 여전히 참조로 복사되므로 한 배열에서 참조 된 개체를 변경하면 다른 배열에 영향을 미칩니다.

여기에 유용한 JavaScript 실행 취소 관리자의 예가 있습니다. http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx


알아. 내가 이것을 구현하고 싶었던 이유는 역 추적으로 CSP 문제를 해결하려고하기 때문입니다. 역 추적을 구현하는 방법 중 하나는 이러한 스냅 샷을 스택으로 복제하여 변수 할당 상태를 "스냅 샷 찍기"와 같을 수 있다고 생각했습니다.
wallyqs

... 그리고 실제로는 아주 나쁜 생각 일 수 있습니다.
wallyqs

이 방법에는 다른 동기화 문제가있을 수 있습니다. :) 스냅 샷을 생성하는 동안 어레이가 변경되지 않는지 어떻게 알 수 있습니까?
markt

저자가 javascript를 사용하여 간단한 실행 취소 관리자를 구현 한 기사에 대한 링크를 추가했습니다.
markt

4

내 접근 방식 :

var temp = { arr : originalArray };
var obj = $.extend(true, {}, temp);
return obj.arr;

원래 배열을 멋지고 깨끗하고 깊게 복제합니다. 원래로 다시 참조되는 객체는 없습니다 :-)


이것은 jquery를 사용하는 최상의 솔루션입니다. 짧고 달다.
John Henckel

1
성능 테스트를 했는데이 솔루션은 JSON.stringify 솔루션보다 약 2 배 빠릅니다.
meehocz

4

lodash는 cloneDeep다음과 같은 기능을 수행합니다.

var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);

4

딥 클론을 구현하려면 JSON.parse (JSON.stringify (your {} or []))를 사용하십시오.

const myObj ={
    a:1,
    b:2,
    b:3
}

const deepClone=JSON.parse(JSON.stringify(myObj));
deepClone.a =12;
console.log("deepClone-----"+myObj.a);
const withOutDeepClone=myObj;
withOutDeepClone.a =12;
console.log("withOutDeepClone----"+myObj.a);


3

eval () (JS의 가장 많이 사용되는 기능이며 코드를 느리게 만듭니다) 및 slice (0) (단순한 데이터 유형에만 작동)

이것은 나에게 가장 좋은 해결책입니다.

Object.prototype.clone = function() {
  var myObj = (this instanceof Array) ? [] : {};
  for (i in this) {
    if (i != 'clone') {
        if (this[i] && typeof this[i] == "object") {
          myObj[i] = this[i].clone();
        } else 
            myObj[i] = this[i];
        } 
    }
  return myObj;
};

3

나는이 문제에 꽤 좌절했다. 분명히 일반적인 배열을 $ .extend 메서드로 보낼 때 문제가 발생합니다. 그래서 문제를 해결하기 위해 약간의 검사를 추가했으며 일반 배열, jQuery 배열 및 모든 객체와 완벽하게 작동합니다.

jQuery.extend({
    deepclone: function(objThing) {
        // return jQuery.extend(true, {}, objThing);
        /// Fix for arrays, without this, arrays passed in are returned as OBJECTS! WTF?!?!
        if ( jQuery.isArray(objThing) ) {
            return jQuery.makeArray( jQuery.deepclone($(objThing)) );
        }
        return jQuery.extend(true, {}, objThing);
    },
});

다음을 사용하여 호출하십시오.

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);

딥 클론? jquery-1.9.1을 사용 하며이 방법을 지원하지 않습니다. 보다 현대적인 버전의 방법입니까?
user5260143

@ user2783091 그는 JQuery를 확장하여 해당 기능을 추가하고 있습니다. 그것은 상자에서 나오는 것이 아닙니다
JorgeeFG

3

이것은 배열, 객체, null 및 기타 스칼라 값을 깊게 복사하고 네이티브가 아닌 함수의 속성을 깊게 복사합니다 (이는 일반적이지 않지만 가능합니다). 효율성을 위해 배열에서 숫자가 아닌 속성을 복사하지 않습니다.

function deepClone (item) {
  if (Array.isArray(item)) {
    var newArr = [];
    for (var i = item.length; i-- > 0;) {
      newArr[i] = deepClone(item[i]);
    }
    return newArr;
  }
  if (typeof item === 'function' && !(/\(\) \{ \[native/).test(item.toString())) {
    var obj;
    eval('obj = '+ item.toString());
    for (var k in item) {
      obj[k] = deepClone(item[k]);
    }
    return obj;
  }
  if (item && typeof item === 'object') {
    var obj = {};
    for (var k in item) {
      obj[k] = deepClone(item[k]);
    }
    return obj;
  }
  return item;
}

3

새로운 ECMAScript 6 Object.assign 메소드를 사용합니다 .

let oldObject = [1,3,5,"test"];
let newObject = Object.assign({}, oldObject);

이 메소드의 첫 번째 인수는 업데이트 할 배열입니다. 새 객체를 원하기 때문에 빈 객체를 전달합니다.

이 구문을 사용할 수도 있습니다.이 구문은 동일하지만 짧습니다.

let newObject = [...oldObject];

이러한 접근 방식은 배열 내의 배열 및 객체에 대한 참조 만 복사하며 이들에 대한 새로운 사본은 만들지 않습니다. 다차원 구조에서는 깨질 것으로 예상됩니다.
벤 휠러

2

다차원 배열을 복제하는 간단한 재귀 배열 방법을 발명 할 수 있습니다. 중첩 배열 내의 객체는 소스 배열의 해당 객체에 대한 참조를 유지하지만 배열은 그렇지 않습니다.

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

var arr = [ 1, 2, 3, 4, [ 1, 2, [ 1, 2, 3 ], 4 , 5], 6 ],
    brr = arr.clone();
brr[4][2][1] = "two";
console.log(JSON.stringify(arr));
console.log(JSON.stringify(brr));


2

JavaScript에서 배열 및 객체 복사는 원점 값을 변경하므로 깊은 복사가 이에 대한 솔루션입니다.

딥 카피는 실제로 새로운 배열을 생성하고 값을 복사하는 것을 의미합니다.

JSON.parseJSON.stringify깊은 복사에 가장 간단한 방법입니다. 이 JSON.stringify()메소드는 JavaScript 값을 JSON 문자열로 변환합니다.JSON.parse() JSON 문자열을 구문 분석하여 문자열에 설명 된 JavaScript 값 또는 오브젝트를 구성합니다.

// 딥 클론

let a = [{ x:{z:1} , y: 2}];
let b = JSON.parse(JSON.stringify(a));
b[0].x.z=0

console.log(JSON.stringify(a)); //[{"x":{"z":1},"y":2}]
console.log(JSON.stringify(b)); // [{"x":{"z":0},"y":2}]

자세한 내용은 여기를 읽으십시오


1
이것이 가장 좋은 해결책입니다. 감사합니다.
니콜라이

1

jQuery로 :

var target= [];
$.each(source, function() {target.push( $.extend({},this));});

1

다음 코드는 객체와 배열딥 카피를 재귀 적으로 수행 합니다 .

function deepCopy(obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
    var out = [], i = 0, len = obj.length;
    for ( ; i < len; i++ ) {
        out[i] = arguments.callee(obj[i]);
    }
    return out;
}
if (typeof obj === 'object') {
    var out = {}, i;
    for ( i in obj ) {
        out[i] = arguments.callee(obj[i]);
    }
    return out;
}
return obj;
}

출처


arguments.callee엄격 모드에서는 사용할 수 없으며 그렇지 않으면 성능 문제가 있습니다.
Brett Zamir 님이


0

필자 Object.create는 모든 최신 브라우저에서 지원되는 JavaScript 구조를 주로 딥 클로닝하는 일반적인 방법을 작성했다고 생각 합니다. 코드는 다음과 같습니다

function deepClone (item) {
  if (Array.isArray(item)) {
    var newArr = [];

    for (var i = item.length; i-- !== 0;) {
      newArr[i] = deepClone(item[i]);
    }

    return newArr;
  }
  else if (typeof item === 'function') {
    eval('var temp = '+ item.toString());
    return temp;
  }
  else if (typeof item === 'object')
    return Object.create(item);
  else
    return item;
}

Object.createitem객체의 프로토 타입으로 취급 되지만 복제와 다릅니다. 경우 item수정, 변경의 "복제"반대에 반영됩니다. 이 방법은 작동하지 않습니다.
Brett Zamir 님이

0

객체를 복제하기 위해 ECMAScript 6을 제안하려고했습니다 reduce().

const newArray=myArray.reduce((array, element)=>array.push(Object.assign({}, element)), []);

그러나 솔직히 @dinodsaurus의 답변이 더 좋습니다. 나는이 버전을 다른 옵션으로 여기에 넣고 있지만 개인적 map()으로 @dinodsaurus가 제안한대로 사용할 것입니다.



0
       var game_popularity = [
            { game: "fruit ninja", popularity: 78 },
            { game: "road runner", popularity: 20 },
            { game: "maze runner", popularity: 40 },
            { game: "ludo", popularity: 75 },
            { game: "temple runner", popularity: 86 }
        ];
        console.log("sorted original array before clonning");
        game_popularity.sort((a, b) => a.popularity < b.popularity);
        console.log(game_popularity);


        console.log("clone using object assign");
        const cl2 = game_popularity.map(a => Object.assign({}, a));
        cl2[1].game = "clash of titan";
        cl2.push({ game: "logan", popularity: 57 });
        console.log(cl2);


        //adding new array element doesnt reflect in original array
        console.log("clone using concat");
        var ph = []
        var cl = ph.concat(game_popularity);

        //copied by reference ?
        cl[0].game = "rise of civilization";

        game_popularity[0].game = 'ping me';
        cl.push({ game: "angry bird", popularity: 67 });
        console.log(cl);

        console.log("clone using ellipses");
        var cl3 = [...game_popularity];
        cl3.push({ game: "blue whale", popularity: 67 });
        cl3[2].game = "harry potter";
        console.log(cl3);

        console.log("clone using json.parse");
        var cl4 = JSON.parse(JSON.stringify(game_popularity));
        cl4.push({ game: "home alone", popularity: 87 });
        cl4[3].game ="lockhead martin";
        console.log(cl4);

        console.log("clone using Object.create");
        var cl5 = Array.from(Object.create(game_popularity));
        cl5.push({ game: "fish ville", popularity: 87 });
        cl5[3].game ="veto power";
        console.log(cl5);


        //array function
        console.log("sorted original array after clonning");
        game_popularity.sort((a, b) => a.popularity < b.popularity);
        console.log(game_popularity);


        console.log("Object.assign deep clone object array");
        console.log("json.parse deep clone object array");
        console.log("concat does not deep clone object array");
        console.log("ellipses does not deep clone object array");
        console.log("Object.create does not deep clone object array");


        Output:


        sorted original array before clonning
        [ { game: 'temple runner', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 } ]
        clone using object assign
        [ { game: 'temple runner', popularity: 86 },
        { game: 'clash of titan', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'logan', popularity: 57 } ]
        clone using concat
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'angry bird', popularity: 67 } ]
        clone using ellipses
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'blue whale', popularity: 67 } ]
        clone using json.parse
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'lockhead martin', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'home alone', popularity: 87 } ]
        clone using Object.create
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'veto power', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'fish ville', popularity: 87 } ]
        sorted original array after clonning
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'veto power', popularity: 40 },
        { game: 'road runner', popularity: 20 } ]

        Object.assign deep clone object array
        json.parse deep clone object array
        concat does not deep clone object array
        ellipses does not deep clone object array
        Object.create does not deep clone object array
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.