Here’s a trick question:
const arr = Array(5).fill([]);
const arr2 = arr.map((subArr, i) => subArr.push(i));
What is the final value of arr
? And the final value of arr2
?
This might be something you see people asking in an interview... and before you go console.log({ arr, arr2 })
, it’s important to know the why
more than the answer.
An array
is a value that will always be passed “as reference”, which means it’s pointing somewhere in memory and it simply uses that.
In contrast, a value like a string
or a number
is passed “by value”, meaning it’s copied to where it’s needed.
And as weird as it might seem when you say it to fill
with []
you’re telling Javascript to use the same reference in all instances.
So, when you map, you’re pushing the index to the same reference, over and over.
What about the second one then?
Well... that’s even more trick! Because that’s just what push
returns!
And if you didn’t know... push
returns the length of the array after the push.
And since it’s inside a map
, that returns a new array... it’s easy to understand what’s going on.
The result
And so it prints this:
{
arr: [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]],
arr2: [1, 2, 3, 4, 5]
}
And not gonna lie...
This didn’t come from an interview or anything like it... but from a test I was doing that as you might have imagined, wasn’t doing what I wanted it to do.
The “fix”:
const arr = Array(5).fill().map(() => []);
const arr2 = arr.map((subArr, i) => subArr.push(i));
console.log({ arr, arr2 });
/*
{
arr: [ [ 0 ], [ 1 ], [ 2 ], [ 3 ], [ 4 ] ],
arr2: [ 1, 1, 1, 1, 1 ]
}
*/
Just Array(5).map(() => [])
doesn’t work, since Array(n)
creates an array of “empty slots” that you can access directly, but you can’t do much else, so you need the fill()
to replace those “voids” with undefined
.
Why does this work?
This one works because map
iterates over the array and each of the []
is actually a new
object that is passed by reference since each iteration uses a new scope.
If you were to initialize a []
outside and pass it... then we would be back to square one.