Generating JS multi dimensional arrays edge cases
tl;dr
Don’t use Array#fill
to generate multi dimensional arrays
Use other methods instead, like this for example:
Array.from(
{ length: 3 },
() => Array.from({ length: 3 })
)
Array(3).fill().map(
() => Array(3).fill()
)
Long version
One of many ways to generate an array is to use JS Array constructor:
> a = Array(5)
[ <5 empty items> ]
> a.length
5
Array can be filled with some value using Array#fill
method
> a = Array(5).fill('value')
[ 'value', 'value', 'value', 'value', 'value' ]
> a = Array(5).fill(0)
[ 0, 0, 0, 0, 0 ]
> a = Array(5).fill()
[ undefined, undefined, undefined, undefined, undefined ]
> a[1] = 42
42
> a
[ undefined, 42, undefined, undefined, undefined ]
So far it works fine, but be careful with filling array with a reference type, like an Array
or Object
> b = Array(3).fill(Array(3).fill())
[ [ undefined, undefined, undefined ],
[ undefined, undefined, undefined ],
[ undefined, undefined, undefined ] ]
> b[1][1] = 42
42
> b
[ [ undefined, 42, undefined ],
[ undefined, 42, undefined ],
[ undefined, 42, undefined ] ]
> b[1] === b[2]
true
Each row of such generated array is actually the same object
It’s literally what the documentations says:
arr.fill(value[, start[, end]])
value: Value to fill the array with. (Note all elements in the array will be this exact value.)
MDN web docs
But not everybody has to know that, right?
And using Array#fill
without that knowledge might lead to a hard to track bug in your application
Solutions
Fill the array with some value, and then map through the values
> a = Array(3).fill().map(() => Array(3).fill())
[ [ undefined, undefined, undefined ],
[ undefined, undefined, undefined ],
[ undefined, undefined, undefined ] ]
> a[1][1] = 42
42
> a
[ [ undefined, undefined, undefined ],
[ undefined, 42, undefined ],
[ undefined, undefined, undefined ] ]
Or use other method, like Array.from
> a = Array.from({ length: 3 }, () => Array.from({ length: 3 }))
[ [ undefined, undefined, undefined ],
[ undefined, undefined, undefined ],
[ undefined, undefined, undefined ] ]
> a[1][1] = 42
42
> a
[ [ undefined, undefined, undefined ],
[ undefined, 42, undefined ],
[ undefined, undefined, undefined ] ]
>
Tweet