Skip to main content

Command Palette

Search for a command to run...

The Hidden Trap of Array.prototype.fill()

Updated
โ€ข3 min read

๐Ÿš€ TLDR;

If your initialisation involves populating an array with non-primitive types (arrays, objects, sets, etc.), never use fill() as it creates a single instance of the array/object passed to it, and fills values of the array with its reference.

Use Array.from() with a mapping function to guarantee that every element is a unique, independent instance.

For your next interview problem or complex project, remember this ruleโ€”it might save you hours of painful debugging! Happy coding!


When solving the Top K frequent problem using the bucket approach, I needed an array of N+1 unique slots, where N is the maximum possible frequency (nums.length). Each slot must be an independent array.

My initial line of code looked like this:

JavaScript

const maxFrequency = nums.length;
const buckets = new Array(maxFrequency + 1).fill([]);

๐Ÿง What Actually Happens: Shared References

The core issue is that fill() only accepts a single value as an argument. When that value is a non-primitive type (like an array or an object), JavaScript does the following:

  1. It creates one single empty array in memory: [].

  2. It then puts a reference to this single, same array into every single index of the buckets array.

The Crux: When my frequency map told me to place a number with frequency 3 into buckets[3], I wrote:

JavaScript

buckets[3].push(num); // I thought I was only affecting bucket 3...

But because buckets[3], buckets[0], buckets[1], and all the others were all pointing to the exact same array object in memory, every bucket got the number! My entire bucket structure was completely corrupted. This is why my "Top K" solution was not working correctly for all test cases.


โœ… The Solution: Array.from({ length }, () => [])

The correct way to initialize an array where every element needs to be a unique instance of an object (like a unique bucket array) is to use the Array.from() method with a mapping function.

JavaScript

const maxFrequency = nums.length;
const buckets = Array.from({ length: maxFrequency + 1 }, () => []);

๐Ÿ’ก Why This Works: The Map Function Creates Unique Instances

Array.from() is designed to create a new array from an iterable or array-like object (like { length: N }). Critically, the second argument is a map function that is executed for every index.

The map function here is () => []. For each of the N+1 positions:

  1. Array.from() executes () => [].

  2. The function returns a brand new, unique empty array instance.

MethodCreatesResulting ReferencesImpact on Buckets
fill([])One []All elements point to the same array.Modifying one bucket affects all buckets.
Array.from(..., () => [])N [] instancesEach element points to a unique array.Modifying one bucket affects only that one bucket.

Switching to Array.from() instantly fixed the issue. My buckets were properly isolated, my logic worked, and I finally got that sweet "Accepted" status.

JavaScript

Part 1 of 1

In this series, I'm covering interesting things in JS that I encounter while working...