Comment cloner un tableau d'objets en Javascript?

422

... où chaque objet a également des références à d'autres objets dans le même tableau?

Quand j'ai rencontré ce problème pour la première fois, j'ai pensé à quelque chose comme

var clonedNodesArray = nodesArray.clone()

existerait et recherchait des informations sur la façon de cloner des objets en javascript. J'ai trouvé une question sur StackOverflow (répondue par le même @JohnResig) et il a souligné qu'avec jQuery vous pouviez faire

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

pour cloner un objet. J'ai essayé cela cependant, cela copie uniquement les références des objets dans le tableau. Donc si je

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

la valeur des nœudsArray [0] et clonedNodesArray [0] se révélera être "verte". J'ai essayé

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

qui copie en profondeur un objet, mais j'ai reçu des messages " trop de récursivité " et " dépassement de la pile de contrôle " de Firebug et Opera Dragonfly respectivement.

Comment feriez-vous? Est-ce quelque chose qui ne devrait même pas être fait? Existe-t-il un moyen réutilisable de le faire en Javascript?

wallyqs
la source

Réponses:

106

Le problème avec votre copie superficielle est que tous les objets ne sont pas clonés. Bien que les références à chaque objet soient uniques dans chaque tableau, une fois que vous l'avez finalement saisi, vous avez affaire au même objet qu'auparavant. Il n'y a rien de mal avec la façon dont vous l'avez cloné ... le même résultat se produirait en utilisant Array.slice ().

La raison pour laquelle votre copie profonde rencontre des problèmes est que vous vous retrouvez avec des références d'objets circulaires. Profondeur ira aussi loin que possible, et si vous avez un cercle, il continuera indéfiniment jusqu'à ce que le navigateur s'évanouisse.

Si la structure de données ne peut pas être représentée sous forme de graphique acyclique dirigé, alors je ne suis pas sûr que vous puissiez trouver une méthode polyvalente pour le clonage en profondeur. Les graphiques cycliques fournissent de nombreux cas difficiles, et comme ce n'est pas une opération courante, je doute que quiconque ait écrit une solution complète (si c'est même possible - ce n'est peut-être pas le cas! Mais je n'ai pas le temps d'essayer d'écrire une preuve rigoureuse maintenant.). J'ai trouvé de bons commentaires sur le problème sur cette page .

Si vous avez besoin d'une copie complète d'un tableau d'objets avec des références circulaires, je pense que vous devrez coder votre propre méthode pour gérer votre structure de données spécialisée, de sorte qu'il s'agit d'un clone à plusieurs passes:

  1. Au premier tour, créez un clone de tous les objets qui ne font pas référence à d'autres objets du tableau. Gardez une trace des origines de chaque objet.
  2. Au deuxième tour, reliez les objets ensemble.
Dan Lew
la source
1
Lien fixe pour la réponse @PatrickdeKleijn: web.archive.org/web/20140222022056/http://my.opera.com/…
Mike Szyndel
532

Tant que vos objets contiennent du contenu sérialisable JSON (pas de fonctions, non Number.POSITIVE_INFINITY, etc.), aucune boucle n'est nécessaire pour cloner des tableaux ou des objets. Voici une solution en ligne pure vanille.

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

Pour résumer les commentaires ci-dessous, le principal avantage de cette approche est qu'elle clone également le contenu du tableau, pas seulement le tableau lui-même. Les principaux inconvénients sont sa limite de ne travailler que sur du contenu sérialisable JSON, et ses performances (ce qui est nettement pire qu'une sliceapproche basée).

Vladimir Kharlampidi
la source
118
Cela peut fonctionner pour les données JSON, mais si votre tableau contient des fonctions ou des instances d'objets qui ont des méthodes, dites-leur au revoir.
sp0rkyd0rky
12
soyez prudent si vous avez un tableau qui contient la valeur Infinity. Cette valeur est perdue (est nulle par la suite). ( jsfiddle.net/klickagent/ehm4bd3s )
klickagent.ch
13
Il s'agit généralement d'une mauvaise approche, à moins que votre tableau ne contienne que des primitives et / ou des objets qui eux-mêmes ne contiennent que des chaînes / nombre / primitives booléennes (même nullet undefinedposeront des problèmes, car JSON ne les prend pas en charge). De plus, c'est une opération beaucoup moins efficace que old_array.slice(0);, qui devrait fonctionner à la fois mieux et plus rapidement.
XML
2
si l'objet du tableau a DateTime, alors la chaîne sera retournée au lieu de DateTime! nouvelle date! == JSON.parse (JSON.stringify (nouvelle date))
MarkosyanArtur
2
La ligne clé de la question de l'OP, que cette réponse ci-dessus ignore complètement: ... où chaque objet a également des références à d'autres objets dans le même tableau?
XML
288

J'ai résolu le clonage d'un tableau d'objets avec Object.assign

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

ou encore plus court avec la syntaxe étalée

const newArray = myArray.map(a => ({...a}));
dinodsaurus
la source
15
Mais si myArray contenait un tas de dinosaures, newArray contient un tas d'objets. C'est boiteux, tu n'es pas d'accord?
Matthew James Davis
3
meilleure approche, car elle maintient les fonctions des objets en vie, les rathen puis les perd avec JSON.parse (JSON.stringify (nodesArray))
scipper
14
@MatthewJamesDavis, vous pouvez résoudre ce problème en le remplaçant {}par new Dinosaur().
Agargara
5
copie superficielle pas copie profonde
sultan aslam
1
Cela fonctionne très bien pour un tableau d'objets, si ces objets ne contiennent que des propriétés primitives ... c'est ce dont j'avais besoin, merci
mojave
154

Si tout ce dont vous avez besoin est une copie superficielle, un moyen très simple est:

new_array = old_array.slice(0);
Leopd
la source
6
Je ne pense pas que vous devez passer 0, vous pouvez simplement appeler .slice()au moins en chrome de toute façon
slf
112
Cela ne fonctionne pas vraiment, n'est-ce pas? Je veux dire, ce n'est pas une réponse à la question de savoir comment cloner un tableau d'objets. C'est la solution pour cloner un tableau simple.
bozdoz
35
En fait, cela ne fonctionnera pas pour un tableau d'objets. Le tableau renvoyé par slicesera un nouveau tableau mais contiendra les références aux objets du tableau d'origine.
Sergio A.
4
Cela ne fonctionnera que pour les "génériques" int, chaîne etc. mais pas pour un tableau d'objets.
Stefan Michev
5
pour le tableau d'objets, cela ne clone pas réellement, la mise à jour vers new_array mettra également à jour old_array.
Anas
44

La meilleure façon et la plus à jour de faire ce clone est la suivante:

Utilisation de l' ...opérateur d'étalement ES6.

Voici l'exemple le plus simple:

var clonedObjArray = [...oldObjArray];

De cette façon, nous répartissons le tableau en valeurs individuelles et le plaçons dans un nouveau tableau avec l'opérateur [].

Voici un exemple plus long qui montre les différentes façons dont cela fonctionne:

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
la source
2
Bonne réponse moderne, qui ne fonctionnera pas avec les anciens navigateurs (comme IE 11)
Jealie
1
@Jealie Je vais deviner que KingpinEX cible cette réponse pour les gens qui transposent es6 en quelque chose de plus universellement utile avec Babel ou ce que vous avez.
ruffin
61
Cela copie simplement en profondeur le tableau, pas chaque objet du tableau.
Toivo Säwén
31
Pour suivre ce que @ ToivoSäwén a dit, cela ne copiera pas en profondeur les objets du tableau. Il fera toujours référence aux objets d'origine, donc si vous les mutez, cela affectera également le tableau d'origine.
Joel Kinzel
3
Cela fonctionne uniquement pour les primitives. Essayez ceci: objArray [0] .a = 3; et vous verrez que la référence de l'objet reste la même dans clonedArray.
Sergio Correa
25

Cela fonctionne pour moi:

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

Et si vous avez besoin d'une copie complète des objets du tableau:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend(true, {}, obj);
                  });
viliks
la source
1
Il semble que cela fonctionnerait. J'essaie d'éviter une utilisation intensive de jQuery, donc je ne l'utiliserai pas dans ma situation, mais une boucle for et for ... in fonctionnerait.
bozdoz
19
$.evalJSON($.toJSON(origArray));
elsereturn
la source
2
Vous devrez utiliser le plugin jquery json pour utiliser ce code.google.com/p/jquery-json
wmitchell
32
Sans JQ (très bien dans les navigateurs modernes):JSON.parse(JSON.stringify(origArray));
forresto
J'ai trouvé ce commentaire utile. Dans mon implémentation, j'avais besoin de faire une copie d'un tableau d'objets auxquels des propriétés observables de KnockoutJS étaient appliquées. La copie n'avait besoin que des valeurs, pas de l'observabilité. Pour faire une copie de JUST les valeurs, j'ai utilisé JSON.parse (ko.toJSON (origArray)) OU ko.utils.parseJson (ko.toJSON (origArray)). Juste mes 2 cents et merci de m'aider à arriver à ma solution.
wavedrop
6
JSON.parse(JSON.stringify(origArray));est certainement la solution la plus simple.
yorkw
jQuery est souvent inutile. youmightnotneedjquery.com
ADJenks
9

La carte crée un nouveau tableau à partir de l'ancien (sans référence à l'ancien) et à l'intérieur de la carte, vous créez un nouvel objet et parcourez les propriétés (clés) et affectez des valeurs de l'ancien objet Array aux propriétés correspondantes au nouvel objet.

Cela créera exactement le même tableau d'objets.

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

Je peux avoir un moyen simple de le faire sans avoir à faire de récursivité douloureuse et sans connaître tous les détails les plus fins de l'objet en question. À l'aide de jQuery, convertissez simplement votre objet en JSON à l'aide de jQuery $.toJSON(myObjectArray), puis prenez votre chaîne JSON et réévaluez-la en objet. BAM! Fait et fait! Problème résolu. :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));
George
la source
21
Certains navigateurs modernes ont la méthode JSON intégrée, vous pouvez donc le faire: JSON.parse (JSON.stringify (MY_ARRAY)) qui devrait être plus rapide. Bonne suggestion.
Nicolas R
1
Et s'ils n'utilisent pas json2 , non eval.
kamranicus
Cela a des performances terribles, mais malheureusement, c'est la meilleure réponse que j'ai vue: /
Dvid Silva
N'évaluez rien avec les données utilisateur. De préférence ne jamais utiliser eval()du tout. C'est un risque pour la sécurité.
ADJenks
8

Je réponds à cette question car il ne semble pas y avoir de solution simple et explicite au problème du "clonage d'un tableau d'objets en 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

Cette solution itère les valeurs du tableau, puis itère les clés d'objet, enregistrant ces dernières dans un nouvel objet, puis poussant ce nouvel objet vers un nouveau tableau.

Voir jsfiddle . Remarque: un simple .slice()ou [].concat()ne suffit pas pour les objets dans le tableau.

bozdoz
la source
merci pour la réponse, mais vous auriez dû mettre en évidence les lacunes de la réponse. Cela ne fonctionne pas lorsque les objets contiennent des objets .. non?
Harsh
il créera une copie superficielle. pas profond
sultan aslam
vous devez ajouter une récursion quelque part
DGoiko
6

JQuery extend fonctionne correctement, il vous suffit de spécifier que vous clonez un tableau plutôt qu'un objet ( notez le [] au lieu de {} comme paramètre de la méthode extend ):

var clonedNodesArray = jQuery.extend([], nodesArray);
Stef
la source
2
Hmm, si vous votez contre, pouvez-vous s'il vous plaît ajouter un commentaire sur la raison pour laquelle vous le faites? Ou pouvez-vous d'abord essayer le code et voir s'il fonctionne ou non? Merci;)
Stef
1
Après avoir changé un objet dans le premier tableau, l'objet dans le second tableau est modifié, donc ce n'est pas ok.
Spikolynn
6

Cette méthode est très simple et vous pouvez modifier votre clone sans modifier le tableau d'origine.

// 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
la source
1
Cela fait une copie superficielle de deux niveaux de profondeur, [...oldArray]et oldArray.slice(0)une copie superficielle d'un niveau de profondeur. C'est donc super utile, mais pas un véritable clone complet.
Ben Wheeler
le vrai clone profond peut être fait à lodash.clonedeeppartir de npm
révélation le
5

Comme Daniel Lew l'a mentionné, les graphiques cycliques ont quelques problèmes. Si j'avais ce problème, j'ajouterais des clone()méthodes spéciales aux objets problématiques ou me souviendrais des objets que j'ai déjà copiés.

Je le ferais avec une variable copyCountqui augmente de 1 à chaque fois que vous copiez dans votre code. Un objet dont copyCountle processus de copie est inférieur à celui en cours est copié. Sinon, la copie, qui existe déjà, doit être référencée. Il est donc nécessaire de lier l'original à sa copie.

Il y a encore un problème: la mémoire. Si vous avez cette référence d'un objet à l'autre, il est probable que le navigateur ne puisse pas libérer ces objets, car ils sont toujours référencés quelque part. Vous devez effectuer une deuxième passe où vous définissez toutes les références de copie sur Null. (Si vous faites cela, vous n'auriez pas besoin d'un copyCountmais un booléen isCopiedserait suffisant, car vous pouvez réinitialiser la valeur lors de la deuxième passe.)

Georg Schölly
la source
4

Array.slice peut être utilisé pour copier un tableau ou une partie d'un tableau. Http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html Cela fonctionnerait avec des chaînes et des nombres .. - changer une chaîne dans un tableau n'affecterait pas l'autre - mais les objets sont toujours simplement copiés par référence, donc les modifications apportées aux objets référencés dans un tableau auraient un effet sur l'autre tableau.

Voici un exemple de gestionnaire d'annulation JavaScript qui pourrait être utile pour cela: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx

markt
la source
Je connais. La raison pour laquelle je voulais implémenter cela est parce que j'essaie de résoudre un problème CSP avec le retour arrière. Je pensais que l'un des moyens d'implémenter le backtracking pourrait être comme "prendre des instantanés" l'état de l'affectation des variables en ... clonant ces instantanés dans une pile.
wallyqs
... et bien, cela pourrait en fait être une très mauvaise idée.
wallyqs le
Cette approche pourrait avoir d'autres complications de synchronisation :) .. Comment savez-vous que la baie n'est pas modifiée pendant que vous prenez un instantané?
Markt
Ajout d'un lien vers un article où l'auteur a implémenté un simple gestionnaire d'annulation à l'aide de javascript ..
markt
4

Mon approche:

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

me donne un clone agréable, propre et profond du tableau d'origine - avec aucun des objets référencés à l'original :-)

nébuleuses
la source
C'est la meilleure solution en utilisant jquery. court et doux.
John Henckel
1
J'ai fait un test de performance et cette solution semble être environ 2 fois plus rapide que la solution JSON.stringify.
meehocz
4

lodash a une cloneDeepfonction à cet effet:

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

Si vous souhaitez implémenter un clone profond, utilisez JSON.parse (JSON.stringify (votre {} 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
la source
3

oubliez eval () (est la fonctionnalité la plus mal utilisée de JS et rend le code lent) et slice (0) (fonctionne uniquement pour les types de données simples)

C'est la meilleure solution pour moi:

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
la source
3

J'étais assez frustré par ce problème. Apparemment, le problème se pose lorsque vous envoyez un tableau générique à la méthode $ .extend. Donc, pour le corriger, j'ai ajouté une petite vérification, et cela fonctionne parfaitement avec les tableaux génériques, les tableaux jQuery et tous les objets.

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

Appelez en utilisant:

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);
Brak
la source
deepclone? J'utilise jquery-1.9.1 et il ne prend pas en charge cette méthode. Est-ce une méthode de version plus moderne?
user5260143
@ user2783091 il étend JQuery pour ajouter cette fonction. Ce n'est pas quelque chose qui sort de la boîte
JorgeeFG
3

Cela copie en profondeur les tableaux, les objets, les valeurs nulles et autres valeurs scalaires, et copie également en profondeur toutes les propriétés des fonctions non natives (ce qui est assez rare mais possible). (Pour plus d'efficacité, nous n'essayons pas de copier des propriétés non numériques sur des tableaux.)

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
la source
3

J'utilise la nouvelle méthode ECMAScript 6 Object.assign :

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

le premier argument de cette méthode est le tableau à mettre à jour, on passe un objet vide car on veut avoir un nouvel objet.

nous pouvons également utiliser cette syntaxe, qui est la même mais plus courte:

let newObject = [...oldObject];
Chtiwi Malek
la source
Notez que ces approches copieront uniquement les références des tableaux et des objets dans le tableau et n'en feront pas de nouvelles copies. Attendez-vous à ce que cela se brise pour les structures multidimensionnelles.
Ben Wheeler
2

Nous pouvons inventer une méthode de tableau récursif simple pour cloner des tableaux multidimensionnels. Alors que les objets dans les tableaux imbriqués conservent leur référence aux objets correspondants dans le tableau source, les tableaux ne le seront pas.

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
la source
2

En JavaScript, la copie de tableaux et d'objets modifie les valeurs d'origine, donc la copie profonde est la solution pour cela.

Une copie profonde signifie réellement créer un nouveau tableau et copier les valeurs, car quoi qu'il arrive, cela n'affectera jamais celui d'origine.

JSON.parseet JSON.stringifyest le moyen le meilleur et le plus simple de copier en profondeur. La JSON.stringify()méthode convertit une valeur JavaScript en chaîne JSON. La JSON.parse()méthode analyse une chaîne JSON, en construisant la valeur ou l'objet JavaScript décrit par la chaîne.

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

Pour plus de détails: lire ici

Bijay Rai
la source
1
C'est la meilleure solution. Je vous remercie.
Nikolay
1

avec jQuery:

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

Le code suivant effectuera récursivement une copie en profondeur des objets et du tableau :

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

La source

Franck Dernoncourt
la source
arguments.calleen'est pas disponible en mode strict et a des problèmes de performances sinon.
Brett Zamir
0

Je pense que j'ai réussi à écrire une méthode générique de clonage en profondeur de toute structure JavaScript utilisant principalement Object.createqui est prise en charge dans tous les navigateurs modernes. Le code est comme ceci:

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
la source
Object.createsera traité itemcomme le prototype de l'objet, mais c'est différent du clonage. Si itemest modifié, les changements seront reflétés dans son "clone" et vice versa. Cette approche ne fonctionne pas.
Brett Zamir
0

Pour cloner les objets également, j'allais juste suggérer ECMAScript 6 reduce():

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

Mais franchement, j'aime encore mieux la réponse de @dinodsaurus. Je mets juste cette version ici comme une autre option, mais personnellement, j'utiliserai map()comme suggéré par @dinodsaurus.

Garret Wilson
la source
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
la source