I came across some code which was filling an array of objects like so:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(null).map(getObj);
console.log(arr);
However, I'm wondering what the main purpose of fill(null).map(getObj)
is? It seems redundant as I can simply write the following and get the same resulting array:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(getObj());
console.log(arr);
So, I'm wondering if these two lines of code do exactly the same thing or if there is something I'm missing?
The resulting arrays (top array first method with fill + map
bottom array is only using map
):
Array(3).fill(getObj())
will fill your array with references to the same object, Array(3).fill(null).map(getObj)
will create object per element. See the example below:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(null).map(getObj);
arr[0].b=4;
console.log(JSON.stringify(arr));
const arr1 = Array(3).fill(getObj());
arr1[0].b=4;
console.log(JSON.stringify(arr1))
When it comes to Array.fill it is stated in the documentation that:
When fill gets passed an object, it will copy the reference and fill the array with references to that object.
So using a Array.fill
with objects has somewhat limited application unless you really want to have multiple objects pointing to the same reference. In more than few use cases however that would lead to bugs
if not understood.
For the 2nd case where you do Array(3).fill(null).map(getObj)
this is one of the ways to create a new array based on a given arbitrary size and at the same time fill it with new objects.
The real need for the fill(null)
is due to the fact that calling Array(3)
would only do one thing. Create a new array and set its length
property to 3. That is it!
let arr = Array(3) // returns new array with its "length" property set to 3
console.log(arr) // [empty × 3] <-- browser console
So that array now has only length and bunch of empty
elements. You can't do much with it until it actually has values. Therefore the need for fill
so that you give it any value and then map
through it to set the values you actually want. Using Array.map
and calling each iteration your function guarantees you do not have same references. You could have skipped the fill
step and done something like this:
const getObj = () => ({a: 1, b: 2, c: 3})
// using array destructuring
let arr = [...Array(3)].map(getObj)
arr[0].a = 3
console.log(arr)
// using Array.from
let arr2 = Array.from(Array(3)).map(getObj)
arr2[0].a = 3
console.log(arr2)
There are somewhat shorter and get you the exact same result of filling the array with specified length with objects and not references to the same object.
The trick here is that both would "fill" the array after it is defined with undefined
values instead, after which the map
would fill it with the values we want.
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