Push property to array not working as expected
prajwal.be.21

Hey,

So I have a property called 'tiles' which contains information about a checkers board's state. I'm trying to push this property to an array called 'moves' everytime I make a legal move and at the start of the game. But the problem is, everytime I push the new tiles property, the previous elements in the array change to the values of the latest pushed tiles.

Here is the snippet of code stripped to explain my problem which causes this behaviour.

App = function () {
  var self = this;
  //more code
  wade.loadJson(tilesFile, data, function () {
    self.tiles = wade.cloneObject(data.data.tiles);
  }
  //more code
  this.startGame = function () {
    self.moves.push(self.tiles);
  };
  this.makeMove = function () {
    self.moves.push(self.tiles);
  };
};


So now if I console 'self.moves' all the elements contain values of the latest pushed 'self.tiles'.

Can someone please explain this behaviour and how I can stop older elements being re-written by the latest tiles property and only push it as the last element in the array?

I want to save this information to implement undo move. I want each move's state to be able to go back to previous state with the help of tiles property. Hope I was clear in explaining the problem. Any help would be highly appreciated.

All 4 Comments
prajwal.be.21

Hey, so I think I realized why this is happening.Since objects are passed by reference i guess the value is lost and it is always pointing to the same object.

Can anyone suggest how I can save tiles property by value in an array after each move? I guess I'll have to create a new object and push that each time?

@Gio, any help doing this will be really appreciated. Thanks!

prajwal.be.21

Hey, I got this working and thought I'll share the answer here

self.moves.push(JSON.parse(JSON.stringify(self.tiles)));

We should use JSON.parse(JSON.stringify()) to clone a nested object, I was instructed on stackoverflow..

foxcode

Hi prajwal.be.21

This does indeed look like a pass by reference issue. The act of pushing self.tiles onto the moves array isn't the issue. The issue is you push self.tiles onto the array, but all that does is effectively store a reference to your self.tiles object inside self.moves[0] for example. That means that if you change self.tiles anywhere in your program, it will change the value of self.moves[0] because they are both effectively variables refering to the same object.

JSON.parse JSON.stringify is a common trick to get around this. JSON.parse takes a json string and returns a NEW object. This is the critical part. You are creating a new object that you are storing in self.moves, so changes to self.tiles will have no effect on the contents of self.moves. This is why your fix works.

Hope that makes sense :)


EDIT: I suspect you can probably do this instead, it's a little cleaner though might even do the same thing under the hood

self.moves.push(wade.cloneObject(self.tiles));

 

prajwal.be.21

Hey foxcode,

Thanks for the explanation. And super thanks for the snippet, it does the samething under the hood but my code looks cleaner.

Appreciate it!

Post a reply
Add Attachment
Submit Reply
Login to Reply