Array().fill is secretly broken

Mayank
|
September 13, 2021

There's something weird about Array().fill(). Well, some of you would say Array itself is weird and confusing depending on how its implemented. You say Array('5') to get an array with 5 as its only element and then when you say Array(5), you get an array with 5 empty slots waiting to be fed. If that's not confusing for you, let's not assume it to be the same for someone new to JavaScript. Anyway, cutting it short. Tell me when would you use the fill() method? You just created an empty array and you want to auto populate it with some data you already have. You want to overwrite your array from some index "x" to index "y" with a given value. I am sure a significant number of us would try and grab the fill() method to get this done. Nothing wrong, nothing bad! That's why we have "Array.prototype.fill()".

Before I tell you where can it go wrong, let us ensure that everyone reading this is on the same page. Try going through the naive snippet that follows and see if you can guess the ouput right. Its so naive that you dont need to open and editor and test stuff out. If you already feel confident and know how it works feel free to skip to the last paragraph.

Try on Codepen

Everything looks fine, right? Yes! it does. We tried creating an empty array. We filled it with some number and then we also tried overwriting the array from index 1 to index 3 (4 is not included). What we did not try yet is filling our array with non-primitives. Lets try doing that now.

Try on Codepen

So far there's no problem but hey! I am here to introduce you to a problem. So if you didn't already smell what's burning, let me show you. Lets say we created an empty array and filled it with 5 empty arrays. Imagine an array 'myArray' with 5 empty arrays inside it. Now lets loop through 'myArray' and try populating all the internal arrays one by one. Take a look at the snippet below and without having it run somewhere tell yourself what do you expect the code to do.

Try on Codepen

You say, we'll get something like an array 'myArray' with 5 arrays inside it, each having one value 'x' inside it? Something like so [ [x], [x], [x], [x], [x] ] ? There lies the problem. Try running the snippet now and see what happens. Weird, right? You get something like so  [ [x,x,x,x,x], [x,x,x,x,x], [x,x,x,x,x], [x,x,x,x,x], [x,x,x,x,x] ]. Can you guess what just happened? When you filled your empty 'myArray' with 5 empty arrays, you may have thought that they will be 5 different arrays but that was not the case. Its one array (one reference) that's distributed all across 'myArray'. This is gross. Why would someone want to fill an entire array with the same object? Anyway, this is clearly reflected in the MDN docs if you read the polyfill code to Array.prototype.fill (step 12). Generally, you wouldn't care doing so but then when you get stuck somewhere its always good to checkout what's hidden in the documentation. I was doing some random experiments with radix sort and I enountered this. Even though there are so many other ways you can get this done, let me jsut share a simple work-around if you really want to use fill to achieve what we tried to achieve in our example.

Try on Codepen

written by
Mayank
Web Technology Enthusiast