Array().fill is secretly broken
Tags: javascript, react, vue, node
Published: 2021-09-13 23:48:18

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()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/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 even need to open an editor and test stuff out. If you already feel confident and know how it works feel free to skip to the last paragraph.

{% runkit %}
const myArray = Array(5); // empty array with 5 slots
myArray.fill(); // myArray = [undefined, undefined, ...5 times]
myArray.fill(0); // [0,0,0,0,0]
myArray.fill('zero', 1, 4); // [0,"zero","zero","zero",0]
{% endrunkit %}<br>

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.

{% runkit %}
const myArray = Array(5); // empty array with 5 slots
myArray.fill({x:1, y:2}); // [{x:1,y:2}, ...5 times]
myArray.fill([1,2]); // [[1,2], [1,2], ...5 times]
{% endrunkit %}<br>

![Something is burning gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ct8s6qepmxu5wmh64vcz.gif)<br><hr>

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.

{% runkit %}
const myArray = Array(5); // empty array with 5 slots
myArray.fill([]); // myArray = [[], [], ...5 times]

myArray.forEach(arr => {
  arr.push('x');
});
console.log(myArray); // check the output
{% endrunkit %}<br>

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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill#polyfill) (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](https://codepen.io/mayankav/pen/JjJJRXp) and I enountered this. Even though there are so many other ways you can get this done, let me just share a simple work-around if you really want to use ***fill*** to achieve what we tried to achieve in our example.

{% runkit %}
const yourArray = new Array(5).fill().map(()=> []); // yourArray = [[], [], ...5 times]

yourArray.forEach(arr => {
  arr.push('y');
});

console.log(yourArray); // check the output
{% endrunkit %}
<center><h6>[Try on Codepen](https://codepen.io/mayankav/pen/xxrrRJK)<h6></center><br>


<br><hr>
##Originally Posted Here -
https://mayankav.webflow.io/blog/array-fill-is-secretly-broken