web-dev-qa-db-fra.com

Copier un tableau d'objets dans un autre tableau en javascript (Deep Copy)

Copier un tableau d'objets dans un autre tableau en javascript à l'aide de slice (0) et concat () ne fonctionne pas.

J'ai essayé ce qui suit pour tester si j'obtiens le comportement attendu de la copie en profondeur en utilisant ceci. Mais le tableau d'origine est également en train d'être modifié après avoir apporté des modifications au tableau copié.

var tags = [];
for(var i=0; i<3; i++) {
    tags.Push({
        sortOrder: i,
        type: 'miss'
    })
}
for(var tag in tags) { 
    if(tags[tag].sortOrder == 1) {
        tags[tag].type = 'done'
    }
}
console.dir(tags)

var copy = tags.slice(0)
console.dir(copy)

copy[0].type = 'test'
console.dir(tags)

var another = tags.concat()
another[0].type = 'miss'
console.dir(tags)

Comment puis-je faire une copie complète d'un tableau dans un autre, de sorte que le tableau d'origine ne soit pas modifié si je modifie un tableau de copie?.

18
jsbisht

Essayer

var copy = JSON.parse(JSON.stringify(tags));
65
dangh

Essayez ce qui suit

// Deep copy
var newArray = jQuery.extend(true, [], oldArray);

Pour plus de détails, consultez cette question Quel est le moyen le plus efficace de cloner en profondeur un objet en JavaScript?

14
Marko

Comme mentionné Ici.slice(0) sera efficace pour cloner le tableau avec des éléments de type primitif. Cependant, dans votre exemple, le tableau tags contient des objets anonymes. Par conséquent, toute modification apportée à ces objets dans un tableau cloné est reflétée dans le tableau tags.

La réponse de @ dangh ci-dessus supprime ces objets et en crée de nouveaux. 

Voici un autre fil abordant une situation similaire

4
Bhanuprakash D

Un bon moyen de cloner un tableau d'objets avec ES6 consiste à utiliser la syntaxe spread:

const clonedArray = [...oldArray];

MDN

3
Binaromong

Vous devez juste utiliser la notation '...'.

// THE FOLLOWING LINE COPIES all elements of 'tags' INTO 'copy'
var copy = [...tags]

Quand vous avez un tableau dit x, [... x] crée un nouveau tableau avec toutes les valeurs de x. Faites attention car cette notation fonctionne légèrement différemment sur les objets. Il divise les objets en toutes ses paires clé/valeur. Donc, si vous voulez passer toutes les paires clé-valeur d'un objet dans une fonction, il vous suffit de passer fonction ({... obj})

1
Anant Sinha

Le moyen le plus simple et optimiste de le faire sur une seule ligne est d'utiliser Underscore/Lodash.

laisser a = _.map (b, _.clone)

0
user8876438

Je sais que cette publication est un peu plus ancienne, mais j’ai eu la chance d’avoir trouvé un moyen décent de copier en profondeur des tableaux, même ceux contenant des tableaux, et même des objets, et même les objets contenant des tableaux sont copiés ... avec ce code, c’est que si vous n’avez pas assez de mémoire, je peux voir cet étouffement sur de très grands tableaux de tableaux et d’objets ... Mais, dans la plupart des cas, cela devrait fonctionner. La raison pour laquelle je publie ceci ici est que cela accomplit la demande de l'OP de copier un tableau d'objets par valeur et non par référence ... donc maintenant avec le code (les vérifications proviennent de SO, la fonction de copie principale que j'ai écrite moi-même que quelqu'un d'autre n'a probablement pas écrit auparavant, je ne suis tout simplement pas au courant):

var isArray = function(a){return (!!a) && (a.constructor===Array);}
var isObject = function(a){return (!!a) && (a.constructor===Object);}
Array.prototype.copy = function(){
    var newvals=[],
        self=this;
    for(var i = 0;i < self.length;i++){
        var e=self[i];
        if(isObject(e)){
            var tmp={},
                oKeys=Object.keys(e);
            for(var x = 0;x < oKeys.length;x++){
                var oks=oKeys[x];
                if(isArray(e[oks])){
                    tmp[oks]=e[oks].copy();
                } else { 
                    tmp[oks]=e[oks];
                }
            }
            newvals.Push(tmp);
        } else {
            if(isArray(e)){
                newvals.Push(e.copy());
            } else {
                newvals.Push(e);
            }
        }
    }
    return newvals;
}

Cette fonction (Array.prototype.copy) utilise la récursivité pour se rappeler automatiquement lorsqu'un objet ou un tableau est appelé, renvoyant les valeurs en fonction des besoins. Le processus est assez rapide et fait exactement ce que vous voudriez qu'il fasse: il copie en profondeur un tableau, par valeur ... Testé en chrome, et IE11, et cela fonctionne dans ces deux navigateurs. 

0
Jesse Fender