How to Properly Clone Multidimensional Arrays

February 27, 2020

I was working on applying different board levels to my lights puzzle (still in progress as I'm writing this post). I encountered a problem where the original board was being modified despite using the spread operator (...) to clone it so its data wouldn't be affected.

let boardLevel1 = [
  [0, 0, 0],
  [0, 0, 0],
  [0, 0, 0]
];

// assign board difficulty
state.board = [ ...boardLevel1 ];

// modify board
state.board[0][0] = 1;

The expected behavior was that the boardLevel1 would not be modified.

console.log(state.board);
// [
//   [1, 0, 0],
//   [0, 0, 0],
//   [0, 0, 0]
// ]

console.log(boardLevel1);
// [
//   [0, 0, 0],
//   [0, 0, 0],
//   [0, 0, 0]
// ]

What actually happened was that boardLevel1 was modified. So reassigning boardLevel1 to the state.board whenever the difficulty was selected wouldn't reset the board.

console.log(state.board);
// [
//   [1, 0, 0],
//   [0, 0, 0],
//   [0, 0, 0]
// ]

console.log(boardLevel1);
// [
//   [1, 0, 0],
//   [0, 0, 0],
//   [0, 0, 0]
// ]

What did I do wrong here? The spread operator was supposed to clone the contents of boardLevel1 and assign it into the state's board property.

It turns out, multidimensional arrays (3D arrays or "an array containing arrays") require an extra step.

The Array's map() method can be used to perform a loop through all the elements in the 3D array where you then use the spread operator to clone each individual array.

let boardLevel1 = [
  [0, 0, 0],
  [0, 0, 0],
  [0, 0, 0]
];

// assign board difficulty using the map() method
state.board = boardLevel1.map(row => [ ...row ] );

// modify board
state.board[0][0] = 1;
console.log(state.board);
// [
//   [1, 0, 0],
//   [0, 0, 0],
//   [0, 0, 0]
// ]

console.log(boardLevel1);
// [
//   [0, 0, 0],
//   [0, 0, 0],
//   [0, 0, 0]
// ]

I've only ever used 3D arrays when first learning programming in college and never realized until I came across this bug that there needed to be an extra step when cloning them properly.