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.
