Como você clona uma matriz de objetos em Javascript?

421

... onde cada objeto também tem referências a outros objetos na mesma matriz?

Quando me deparei com esse problema, pensei em algo como

var clonedNodesArray = nodesArray.clone()

existiria e procurou informações sobre como clonar objetos em javascript. Eu encontrei uma pergunta no StackOverflow (respondida pelo mesmo @JohnResig) e ele apontou que com o jQuery você poderia fazer

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

clonar um objeto. Eu tentei isso, porém, isso apenas copia as referências dos objetos na matriz. Então se eu

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

o valor de nodesArray [0] e clonedNodesArray [0] será "verde". Então eu tentei

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

que copia profundamente um objeto, mas recebi mensagens de " muita recursão " e " controle da pilha excedente " do Firebug e do Opera Dragonfly, respectivamente.

Como você faria? Isso é algo que nem deveria ser feito? Existe uma maneira reutilizável de fazer isso em Javascript?

wallyqs
fonte

Respostas:

106

O problema com sua cópia superficial é que todos os objetos não são clonados. Embora as referências a cada objeto sejam únicas em cada matriz, uma vez que você o agarrar, estará lidando com o mesmo objeto de antes. Não há nada de errado com a maneira como você o clonou ... o mesmo resultado ocorreria usando Array.slice ().

A razão pela qual sua cópia detalhada está tendo problemas é porque você está terminando com referências a objetos circulares. O Deep vai tão fundo quanto possível, e se você tiver um círculo, ele continuará infinitamente até que o navegador desmaie.

Se a estrutura de dados não puder ser representada como um gráfico acíclico direcionado, não tenho certeza de que você conseguirá encontrar um método para todos os fins de clonagem profunda. Os gráficos cíclicos fornecem muitos casos complicados e, como não é uma operação comum, duvido que alguém tenha escrito uma solução completa (se é que é possível - pode não ser! Mas não tenho tempo para tentar escrever uma prova rigorosa agora.). Encontrei bons comentários sobre o assunto nesta página .

Se você precisar de uma cópia profunda de uma matriz de objetos com referências circulares, acredito que você precisará codificar seu próprio método para manipular sua estrutura de dados especializada, de modo que seja um clone de várias passagens:

  1. Na primeira rodada, faça um clone de todos os objetos que não fazem referência a outros objetos na matriz. Mantenha um controle das origens de cada objeto.
  2. Na segunda rodada, vincule os objetos.
Dan Lew
fonte
1
Link fixo para a resposta @PatrickdeKleijn: web.archive.org/web/20140222022056/http://my.opera.com/…
Mike Szyndel
531

Desde que seus objetos contenham conteúdo serializável em JSON (sem funções, não Number.POSITIVE_INFINITYetc.), não há necessidade de loops para clonar matrizes ou objetos. Aqui está uma solução de uma linha pura de baunilha.

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

Para resumir os comentários abaixo, a principal vantagem dessa abordagem é que ela também clona o conteúdo da matriz, não apenas a matriz em si. As principais desvantagens são o limite de trabalhar apenas em conteúdo serializável em JSON e o desempenho (que é significativamente pior do que uma sliceabordagem baseada).

Vladimir Kharlampidi
fonte
118
Isso pode funcionar para dados JSON, mas se sua matriz contiver funções ou instâncias de objetos que possuam métodos, diga adeus a eles.
Sp0rkyd0rky
12
tenha cuidado se você tiver uma matriz que contenha o valor Infinito. Este valor é perdido (depois é nulo). ( jsfiddle.net/klickagent/ehm4bd3s )
klickagent.ch 01/02
13
Essa geralmente é uma abordagem ruim, a menos que sua matriz contenha apenas primitivas e / ou objetos que eles mesmos contenham apenas primitivas string / number / boolean (pares nulle undefinedserão problemas, pois o JSON não os suporta). Além disso, é uma operação muito menos eficiente que old_array.slice(0);, que deve funcionar melhor e mais rapidamente.
XML
2
se o objeto da matriz tiver DateTime, a string será retornada em vez de DateTime! Você pode usar o seguinte exemplo: JSON.parse (JSON.stringify (new Date))
#
2
A linha-chave na pergunta do OP, que esta resposta acima ignora completamente: ... onde cada objeto também tem referências a outros objetos dentro da mesma matriz?
XML
288

Resolvi a clonagem de uma matriz de objetos com Object.assign

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

ou ainda mais curto com sintaxe de propagação

const newArray = myArray.map(a => ({...a}));
dinodsauro
fonte
15
Mas se myArray continha um monte de dinossauros, newArray contém um monte de objetos. Isso é coxo, você não concorda?
Matthew James Davis
3
melhor abordagem, uma vez que mantém objetos funções vivo, Rathen, em seguida, perder-los com JSON.parse (JSON.stringify (nodesArray))
scipper
14
@MatthewJamesDavis, você pode resolver isso substituindo {}por new Dinosaur().
Agargara 6/06/19
5
cópia superficial cópia não é profundo
aslam sultão
1
Isso funciona muito bem para um array de objetos, se esses objetos contêm apenas propriedades primitivos ... que é o que eu precisava, graças
mojave
154

Se tudo o que você precisa é de uma cópia superficial, uma maneira realmente fácil é:

new_array = old_array.slice(0);
Leopd
fonte
6
Eu não acho que você tem que passar 0, você pode apenas chamar .slice()pelo menos em cromo de qualquer maneira
SLF
112
Isso realmente não funciona, não é? Quero dizer, não é uma resposta para a pergunta de como clonar uma matriz de objetos. Esta é a solução para clonar uma matriz simples.
bozdoz
35
Na verdade, isso não funcionará para uma matriz de objetos. A matriz retornada por sliceserá uma nova matriz, mas conterá as referências aos objetos originais da matriz.
Sergio A.
4
Isso funcionará apenas para "genéricos" int, string etc., mas não para uma matriz de objetos.
21714 Stefan Michev
5
para a matriz de objetos que na verdade não é clonada, a atualização para o new_array também atualizará o old_array.
Anas
44

A melhor e mais atualizada maneira de fazer esse clone é a seguinte:

Usando o ...operador de expansão ES6.

Aqui está o exemplo mais simples:

var clonedObjArray = [...oldObjArray];

Dessa forma, distribuímos a matriz em valores individuais e a colocamos em uma nova matriz com o operador [].

Aqui está um exemplo mais longo que mostra as diferentes maneiras como funciona:

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} ]

MennyMez
fonte
2
Boa resposta moderna, que não vai trabalhar com navegadores mais antigos (como o IE 11)
Jealie
1
@ Jealie, acho que o KingpinEX está direcionando essa resposta para as pessoas que transpilam o es6 para algo mais universalmente útil com Babel ou o que você tem.
Ruffin
61
Isso apenas copia profundamente a matriz, não cada objeto na matriz.
Toivo Säwén
31
Para acompanhar o que o @ ToivoSäwén disse, isso não irá copiar profundamente os objetos na matriz. Ele ainda fará referência aos objetos originais, portanto, se você os alterar, também afetará a matriz original.
Joel Kinzel
3
Funciona apenas para primitivos. Tente o seguinte: objArray [0] .a = 3; e você verá que a referência do objeto permanece a mesma em clonedArray.
Sergio Correa
25

Isso funciona para mim:

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

E se você precisar de uma cópia profunda dos objetos na matriz:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend(true, {}, obj);
                  });
viliks
fonte
1
Parece que funcionaria. Estou tentando evitar o uso extensivo de jQuery, para não usá-lo na minha situação, mas um loop for e for ... in funcionaria.
bozdoz
19
$.evalJSON($.toJSON(origArray));
elsereturn
fonte
2
Você precisará usar o plugin jquery json para usar esse código.google.com
p/
32
Sem JQ (bom em navegadores modernos):JSON.parse(JSON.stringify(origArray));
forresto
Achei este comentário útil. Na minha implementação, eu precisava fazer uma cópia de uma matriz de objetos que tivessem propriedades observáveis ​​do KnockoutJS aplicadas. A cópia precisava apenas dos valores, não da observabilidade. Para fazer uma cópia de APENAS os valores que usei JSON.parse (ko.toJSON (origArray)) OU ko.utils.parseJson (ko.toJSON (origArray)). Apenas meus 2 centavos e obrigado por me ajudar a chegar à minha solução.
wavedrop
6
JSON.parse(JSON.stringify(origArray));é definitivamente a solução mais simples.
yorkw 23/09/13
jQuery é frequentemente desnecessário. youmightnotneedjquery.com
ADJenks
9

O mapa criará uma nova matriz a partir da antiga (sem referência à antiga) e, dentro do mapa, você criará um novo objeto e iterará sobre as propriedades (chaves) e atribuirá valores do objeto antigo da Matriz às propriedades correspondentes do novo objeto.

Isso criará exatamente a mesma matriz de objetos.

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

Eu posso ter uma maneira simples de fazer isso sem ter que fazer uma recursão dolorosa e sem conhecer todos os detalhes do objeto em questão. Usando o jQuery, basta converter seu objeto em JSON usando o jQuery $.toJSON(myObjectArray), em seguida, pegue sua string JSON e avalie-a novamente em um objeto. BAM! Feito e feito! Problema resolvido. :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));
George
fonte
21
Alguns navegadores modernos têm o método JSON embutido para que você possa fazer isso: JSON.parse (JSON.stringify (MY_ARRAY)), que deve ser mais rápido. Boa sugestão.
Nicolas R
1
E se eles não usam json2 , não eval.
Kamranicus
Isso tem um desempenho terrível, mas infelizmente é a melhor resposta que já vi: /
Dvid Silva
Não avalie nada com os dados do usuário. De preferência, nunca use eval(). É um risco de segurança.
ADJenks
8

Estou respondendo a essa pergunta porque não parece haver uma solução simples e explícita para o problema de "clonar uma matriz de objetos em 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

Essa solução itera os valores da matriz, depois as chaves do objeto, salvando-as em um novo objeto e, em seguida, enviando esse novo objeto para uma nova matriz.

Veja jsfiddle . Nota: um simples .slice()ou [].concat()não é suficiente para os objetos dentro da matriz.

bozdoz
fonte
obrigado pela resposta, mas você deveria ter destacado as deficiências da resposta. Não funciona quando os objetos têm objetos .. certo?
áspero
ele criará uma cópia superficial. não deep
sultan aslam 13/02/19
você precisa adicionar a recursividade em algum lugar
DGoiko
6

A extensão do JQuery está funcionando bem, basta especificar que você está clonando uma matriz em vez de um objeto ( observe o parâmetro [] em vez de {} como parâmetro no método extend ):

var clonedNodesArray = jQuery.extend([], nodesArray);
Stef
fonte
2
Hmm, se você recusar isso, você pode adicionar um comentário sobre o motivo? Ou você pode primeiro tentar o código e ver se funciona ou não? Obrigado;) #
314 Stef #
1
Depois de alterar um objeto na primeira matriz, o objeto na segunda matriz é modificado, portanto não está ok.
Spikolynn 25/10/19
6

Este método é muito simples e você pode modificar seu clone sem modificar a matriz original.

// 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'}]

Rafael Grilli
fonte
1
Isto faz uma cópia superficial que é dois níveis de profundidade, enquanto [...oldArray]e oldArray.slice(0)fazer uma rasa copiar um profundo nível. Portanto, isso é super útil, mas não um clone profundo e real.
Ben Wheeler
verdadeiro clone profundo pode ser feito usando a lodash.clonedeeppartir da npm
revelt 27/01
5

Como Daniel Lew mencionou, os gráficos cíclicos têm alguns problemas. Se eu tivesse esse problema, adicionaria clone()métodos especiais aos objetos problemáticos ou lembraria quais objetos eu já copiei.

Eu faria isso com uma variável copyCountque aumenta em 1 toda vez que você copia seu código. Um objeto que tem um valor mais baixocopyCount processo de cópia que o atual é copiado. Caso contrário, a cópia, que já existe, deve ser referenciada. Isso torna necessário vincular o original à sua cópia.

Ainda existe um problema: Memória. Se você tiver essa referência de um objeto para outro, é provável que o navegador não consiga liberar esses objetos, pois eles sempre são referenciados de algum lugar. Você precisaria fazer uma segunda passagem para definir todas as referências de cópia para Nulo. (Se você fizer isso, não precisaria ter um, copyCountmas um booleano isCopiedseria suficiente, pois você pode redefinir o valor na segunda passagem.)

Georg Schölly
fonte
4

Array.slice pode ser usado para copiar uma matriz ou parte de uma matriz. Http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html Isso funcionaria com seqüências e números .. - alterando uma sequência em uma matriz não afetaria a outra - mas os objetos ainda são copiados apenas por referência; portanto, as alterações nos objetos referenciados em uma matriz afetariam a outra matriz.

Aqui está um exemplo de um gerenciador de desfazer JavaScript que pode ser útil para isso: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx

Markt
fonte
Eu sei. A razão pela qual eu quis implementar isso é porque estou tentando resolver um problema de CSP com retorno. Eu pensei que uma das maneiras de implementar o backtracking poderia ser como "tirar instantâneos" do estado da atribuição das variáveis ​​... clonando esses instantâneos em uma pilha.
28409 wallyqs
... e bem, pode ser realmente uma péssima ideia.
28409 wallyqs
Essa abordagem pode ter outras complicações de sincronização :) .. Como você sabe que a matriz não está sendo alterada enquanto você tira um instantâneo?
markt
Adicionado um link para um artigo onde o autor implementou um gerenciador de reversão simples usando javascript ..
Markt
4

Minha abordagem:

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

fornece um clone agradável, limpo e profundo da matriz original - sem nenhum dos objetos referenciados de volta ao original :-)

nebulosas
fonte
Esta é a melhor solução usando jquery. curto e grosso.
John Henckel
1
Fiz um teste de desempenho e essa solução parece ser aproximadamente duas vezes mais rápida que a solução JSON.stringify.
meehocz
4

O lodash tem cloneDeepfunção para esses propósitos:

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

Se você deseja implementar o clone profundo, use JSON.parse (JSON.stringify (your {} ou []))

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);

sudheer nunna
fonte
3

esqueça eval () (é o recurso mais mal utilizado do JS e torna o código lento) e slice (0) (funciona apenas para tipos de dados simples)

Esta é a melhor solução para mim:

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;
};
krupar
fonte
3

Fiquei bastante frustrado com esse problema. Aparentemente, o problema surge quando você envia uma matriz genérica para o método $ .extend. Portanto, para corrigi-lo, adicionei uma pequena verificação e funciona perfeitamente com matrizes genéricas, matrizes jQuery e quaisquer objetos.

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);
    },
});

Invoque usando:

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);
Brak
fonte
deepclone? Eu uso o jquery-1.9.1 e ele não suporta esse método. É método de versão mais moderna?
User5260143
@ user2783091 ele está estendendo o JQuery para adicionar essa função. Não é algo que sai da caixa #
JorgeeFG
3

Isso copia profundamente matrizes, objetos, valores nulos e outros valores escalares e também copia profundamente quaisquer propriedades em funções não nativas (o que é bastante incomum, mas possível). (Por questões de eficiência, não tentamos copiar propriedades não numéricas em matrizes.)

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;
}
Brett Zamir
fonte
3

Eu uso o novo método ECMAScript 6 Object.assign :

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

o primeiro argumento desse método é a matriz a ser atualizada; passamos um objeto vazio porque queremos ter um novo objeto.

também podemos usar esta sintaxe, que é a mesma, mas mais curta:

let newObject = [...oldObject];
Chtiwi Malek
fonte
Observe que essas abordagens copiarão apenas referências para matrizes e objetos dentro da matriz e não farão novas cópias delas. Espere que isso se quebre para estruturas multidimensionais.
Ben Wheeler
2

Podemos inventar um método simples de matriz recursiva para clonar matrizes multidimensionais. Enquanto os objetos nas matrizes aninhadas mantêm sua referência aos objetos correspondentes na matriz de origem, as matrizes não.

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));

Redu
fonte
2

No JavaScript, a cópia da matriz e do objeto altera os valores de origem; portanto, a cópia profunda é a solução para isso.

Uma cópia profunda significa, na verdade, criar uma nova matriz e copiar os valores, pois o que quer que aconteça nunca afetará a origem.

JSON.parsee JSON.stringifyé a melhor e mais simples maneira de copiar em profundidade. O JSON.stringify()método converte um valor JavaScript em uma string JSON. O JSON.parse()método analisa uma string JSON, construindo o valor ou o objeto JavaScript descrito pela string.

// Deep Clone

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}]

Para mais detalhes: Leia aqui

Bijay Rai
fonte
1
essa é a melhor solução. Obrigado.
Nikolay
1

com jQuery:

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

O código a seguir executará recursivamente uma cópia profunda de objetos e matriz :

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

Fonte

Franck Dernoncourt
fonte
arguments.calleenão está disponível no modo estrito e tem problemas de desempenho caso contrário.
Brett Zamir
0

Eu acho que conseguiu escrever um método genérico de clonagem profunda de qualquer estrutura JavaScript usando principalmente, Object.createque é suportada em todos os navegadores modernos. O código é assim:

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;
}
ozantunca
fonte
Object.createtratará itemcomo o protótipo do objeto, mas isso é diferente da clonagem. Se itemfor modificado, as alterações serão refletidas em seu "clone" e vice-versa. Essa abordagem não funciona.
Brett Zamir
0

Para clonar os objetos, eu sugeria o ECMAScript 6 reduce():

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

Mas, francamente, eu gosto ainda mais da resposta do @dinodsaurus. Estou apenas colocando esta versão aqui como outra opção, mas pessoalmente vou usar map()como sugerido por @dinodsaurus.

Garret Wilson
fonte
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
Sangram
fonte