Array.fill() is pretty useful when you need to create an array with some default values.

For example:

const numbers = Array(5).fill(0); console.log(numbers); // [0, 0, 0, 0, 0] 

Nothing unusual there.

But things get a bit confusing when you use it with objects.

Say you want three tasks, all initially incomplete:

const tasks = Array(3).fill({ done: false }); tasks[0].done = true; console.log(tasks); 

You might expect:

[ { done: true }, { done: false }, { done: false } ] 

But the actual result is:

[ { done: true }, { done: true }, { done: true } ] 

The reason is that fill() doesn't create a new object for each position.

It puts the same object reference into every slot.

You can check that with:

console.log(tasks[0] === tasks[1]); // true 

So changing a property through one array element also affects the others.

If you need separate objects, Array.from() works better here:

const tasks = Array.from( { length: 3 }, () => ({ done: false }) ); tasks[0].done = true; console.log(tasks); 

Now you get:

[ { done: true }, { done: false }, { done: false } ] 

Each call to the callback creates a new object.

The same issue can happen with nested arrays:

const grid = Array(3).fill(Array(3).fill(0)); grid[0][0] = 1; console.log(grid); // [[1, 0, 0], [1, 0, 0], [1, 0, 0]] 

A better way to create that grid is:

const grid = Array.from( { length: 3 }, () => Array(3).fill(0) ); 

Using fill() with numbers, strings, or booleans is fine. Just be careful when the value is an object or array.

It's a small detail, but it can cause some confusing bugs if you don't notice it.