Recenly I was working through a problem on LeetCode that required the creation of an X-by-X racetrack. The input would direct a car through a series of moves around the racetrack, printing the board with each movement. Simple enough?
I created my matrix- in this case 4x4- and set my car’s starting position:
const raceTrack = Array(4).fill(Array(4).fill(0));
raceTrack[1][2] = 1;
I happily clacked away at my keyboard, implementing the rest of the solution with little suspicion that I had introduced a bug in my very first line of code. When I went to print the initial board, this is what I saw:
0010
0010
0010
0010
If you’ve been in the JS world for any length of time you’re probably not surprised by this output. The error I had made- a classic error, really- was confusing pass by reference for pass by value. The MDN docs for .fill()
make this perfectly clear:
When fill gets passed an object, it will copy the reference and fill the array with references to that object.
Let’s break it down:
The initial Array(4)
creates an array with 4 empty items. It’s then filled with the result of Array(4).fill(0). But what exactly is Array(4).fill(0)
? It’s a single array, passed by reference to each of the four empty spaces in the first Array(4)
. Therefore, when I went to update the racetrack with the racer and then log the result, what was displayed was not a two dimensional array containing four different arrays, but a two dimensional array containing four representations of the same, now updated array.
All unwell and bad. So then how to fix it?
Array(4).fill(0).map(() => Array(4).fill(0));
By filling the first array with zeroes and then mapping each to the result of a callback that returns Array(4).fill(0)
we are given a brand new array with each iteration. After updating the initial code, everything works as intended:
const raceTrack = Array(4).fill(0).map(() => Array(4).fill(0));
raceTrack[1][2] = 1;
printTrack(raceTrack);
/*
0000
0010
0000
0000
*/