J'ai donc une propriété dans une classe appelée 'tiles' qui contient des informations sur l'état d'un jeu de plateau de dames. J'essaie de pousser cette propriété vers un tableau appelé «coups» chaque fois que je fais un mouvement légal et au début de la partie. Mais le problème est que chaque fois que je pousse la nouvelle propriété tiles, les éléments précédents du tableau moves changent pour les valeurs des dernières mosaïques poussées.
Je comprends que cela se produit parce que l'objet est passé par référence et donc remplace les anciens éléments du tableau, car ils pointent maintenant vers le même objet, qui est la dernière valeur des tuiles de propriété. Donc, avec mon code ci-dessous, y a-t-il un moyen de pousser cet objet non pas par référence, mais par chaque état individuel de «tuiles» qui a résulté en raison de mouvements légaux.
Voici mon extrait: App.js
App = function () { var self = this; self.tiles = []; // this is populated with objects from a json file //code to fetch json and save it to self.tiles //more code this.startGame = function () { //other code self.moves.push(self.tiles); }; this.makeMove = function () { //other code self.moves.push(self.tiles); }; };
Donc, ce que j'attends du tableau self.moves, les tuiles doivent pointer vers des objets différents au lieu du même objet. Il devrait contenir différents états de self.tiles mais pour le moment, lorsque je pousse la propriété, les éléments du tableau 'moves' sont écrasés par la dernière valeur self.tiles.
Toute aide pour résoudre ce problème sera être très apprécié. Merci!
3 Réponses :
Vous devez utiliser JSON.parse (JSON.stringify ())
pour cloner un objet imbriqué.Vous pouvez utiliser Object.assign
pour cloner un objet peu profond
App = function () { var self = this; self.tiles = []; // this is populated with objects from a json file //code to fetch json and save it to self.tiles //more code this.startGame = function () { //other code self.moves.push(JSON.parse(JSON.stringify(self.tiles))); }; this.makeMove = function () { //other code self.moves.push(JSON.parse(JSON.stringify(self.tiles))); }; };
Super merci Maheer! Ça marche comme prévu. Appréciez-le!
La seule façon de résoudre votre problème est de transmettre le clone de l'objet que vous souhaitez insérer dans le vecteur. Dans de tels cas, vous écririez normalement une méthode clone () sur votre objet qui renvoie une copie complète de lui-même. L'objet retourné par cette méthode peut être poussé vers le tableau.
Merci Ravi, le notera également.
Je l'ai bidouillé pendant un moment et j'ai trouvé que vous pouvez utiliser l'opérateur de propagation comme ceci:
var a = {b: 1, c: 2} var array1 = [] array1.push({...a}) a.c=3 console.log(array1) // [0: {b: 1, c: 2}] console.log(a) // {b: 1, c: 3}
Cela ne fait qu'une copie superficielle (similaire à Object .assign mais à l'exclusion du prototype). Si a
était {level1: {level2: 2}}
et que vous ferez ({... a}). Level1.level2 = 8 code> alors vous muteriez la valeur
a
.
donc ce que vous dites, c'est que les accessoires de l'objet "cloné" sont vraiment des références à a.prop1, a.prop2? TIL
la classe de tuiles implémente-t-elle le modèle .clone ()? si oui, utilisez self.moves.push (self.tiles.clone ())
Je suppose que oui, car dans le rappel, j'ai le code suivant. self.tiles = wade.cloneObject (data.data.tiles);
Hey Erch, désolé, je n'ai pas implémenté le modèle .clone () et j'étais confus au sujet de la fonction cloneObject que j'utilise et qui est livrée avec l'ES6 Game Engine. Mais la réponse de Maheer a fait l'affaire ... Mais merci quand même!
"l'objet est passé par référence" C'est une erreur courante de supposer cela, mais JavaScript est un langage pass-par-valeur. Les objets sont des valeurs de type de référence , mais ce n'est pas la même chose que le passage par référence.
Merci pour la correction Felix.