Need a little help

Need a little help
0

#1

I’m working my way through the game of life challenge and ended up with a bug. It took me a while to track it down but here is the problem:

var gameData = function()
   {
   this.board = [];

  this.update = function()
    {
      let buffer = this.board.slice(0); //Making a copy of board
      //then inside my loop:
        if(x){ 
          buffer[y][x] = true; //This is where I'm having problems
         //It is also setting this.board[y][x] == true and I don't know why
        }
    //After the loop:
    this.board = buffer.slice(0);
    };
  }

Now, according to the docs ‘slice’ returns a “new” array object, so I have no clue why the board object would be changing at the same time I’m setting the buffer object. If anyone can point out what I’m missing I would be very grateful.


#2

Hi,

I would like to welcome you to the club of surprising javascript behavior !

I had the same issue when I was implementing the Tic Tac Toe game. What you need to know is that the buffer keeps a link to the board array. Why ? I myself didn’t understand why, but I know how to avoid this.

Try this :

let buffer = JSON.parse(JSON.stringify(this.board));

What the code does is to simulate a deep copy of the board array. That way you end up with a ‘truly’ new array as buffer.

The problem here is related to Javascript shallow copy and deep copy. This is object cloning. If you want to learn more about it, check this link at stackoverflow.

Good luck.


#3

Actually i also encountered this kind of problem long ago not exactly in the way you did but it happened when i was trying to make a copy of an array, and when i was manipulating the new/copied array it was affecting the original array as well then it occurred to me that it might be the case where the value is passed by reference, so i made a for loop and pushed each value of the new array one by one. I was totally stumped when this happened!


#5

Thanks you guys. Both solutions work.

This is a neat trick, but it seems like an ugly work-around to me, Converting the array to a string then back to an array, just doesn’t doesn’t sit right but maybe thats just me,
I ended up going with:

let buffer= this.board.map(function(item){ return item.slice(0); });
This just seems to be a bit “cleaner” and easier to read. It also seems to run a little faster. Anyways thanks again :slight_smile:


#6

@Josh5231

You are right, using map is cleaner. And I am not surprised it goes faster : the built-in array methods are really useful !

I understand why it did copy by reference. I think it’s because it’s a 2d array. The initial code tried to copy the first dimension but seeing that there is content that will be lost, it ends up passing the reference.
Do you think it’s what happen ?

I also came across another solution using jquery :

let buffer =  $.extend(true, {}, this.board);

#7

I’m still not sure why it would pass a reference, but it definitely has something to do with the fact that it is 2d array. About the other solutions you gave, I tried that and ended up with all kinds of errors. It wouldn’t let me me use any of the built in array function. I will have to look into exactly what it’s doing.