I was trying to used Array.prototype.fill method to create a n x n 2D array but the code was buggy and I eventually found out all arrays inside are actually "pointers" to the same array.
Sample:
var matrix = new Array(10).fill(new Array(10), 0);
I thought conceptually this could create a 10 x 10 2D array. However if I assign value to matrix[0][0]:
matrix[0][0] = 1;
The result will actually be:
matrix[0][0] === 1;
matrix[1][0] === 1;
matrix[2][0] === 1;
matrix[3][0] === 1;
matrix[4][0] === 1;
matrix[5][0] === 1;
matrix[6][0] === 1;
matrix[7][0] === 1;
matrix[8][0] === 1;
matrix[9][0] === 1;
and every time if I tried to assign value to any of the position in the matrix, all corresponding positions in other sub-arrays will change as well.
I am wondering why it's happening?
Can anyone please answer this head-scratching question?
I am wondering why it's happening?
Array#fill
takes the value you give it as the first argument, and fills the array with copies of that value.
The value you're giving it is a reference to an array, so naturally what it gives you back is an array filled with copies of that reference. Not copies of the array, copies of the reference.
E.g., it behaves this way for exactly the same reason this code:
var a = new Array(10);
var b = a;
...leaves us with a
and b
both referring to the same array (both containing the same value; a reference to the single array we've created).
Let's throw some Unicode-art at it:
After this code runs:
var a = new Array(10);
var b = a;
we have this in memory (minus a few irrelevant details):
a:Ref89895−−−+ | | +−−−−−−−−−−−−−−−+ +−−−−−>| array | | +−−−−−−−−−−−−−−−+ | | length: 10 | b:Ref89895−−−+ +−−−−−−−−−−−−−−−+
a
and b
contain a reference, which I've shown here as Ref89895 although we never see the actual value. That's what's copied by b = a
, not the array itself.
Similarly, when you do:
var matrix = new Array(10).fill(new Array(10), 0);
you end up with
+−−−−−−−−−−−−−−−+ matrix:Ref89895−−−>| array | +−−−−−−−−−−−−−−−+ | length: 10 | | 0: Ref55462 |--\ | 1: Ref55462 |--\\ | 2: Ref55462 |--\\\ | 3: Ref55462 |--\\\\ +−−−−−−−−−−−−−−−+ | 4: Ref55462 |---+++++->| array | | 5: Ref55462 |--///// +−−−−−−−−−−−−−−−+ | 6: Ref55462 |--//// | length: 10 | | 7: Ref55462 |--/// +−−−−−−−−−−−−−−−+ | 8: Ref55462 |--// | 9: Ref55462 |--/ +−−−−−−−−−−−−−−−+
To create a 10-place array where each of the 10 places is itself a 10-place array of 0, I'd probably use either Array.from
or fill
with map
:
// Array.from
var matrix = Array.from({length: 10}, function() {
return new Array(10).fill(0);
});
// fill and map
var matrix = new Array(10).fill().map(function() {
return new Array(10).fill(0);
});
or in ES2015:
// Array.from
let matrix = Array.from({length: 10}, () => new Array(10).fill(0));
// fill and map
let matrix = new Array(10).fill().map(() => new Array(10).fill(0));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With