Array.prototype.fill()
Overwrites a range of an array in place with a single static value and returns that array.
fill(value)
fill(value, start)
fill(value, start, end)- Added in JavaScript ECMAScript 2015
Parameters
| Parameter | Type | Description |
|---|---|---|
$value | any | The value written into every slot in the range. If it is an object, every slot references that same object. |
$startoptional | number= 0 | Zero-based index to start filling at. Negative values count back from the end. |
$endoptional | number= array.length | Zero-based index to stop before. Negative values count back from the end. |
Return value
ArrayThe same array, modified in place, with the selected range set to value.
Errors
Throws a TypeError if called on null or undefined, or when a target index cannot be written — for example on a frozen array with a non-empty range, which throws in strict and sloppy mode alike. Sealed arrays are unaffected, because sealing leaves existing elements writable.
fill() writes one value into every index from start up to but not including end. It mutates the receiver and returns it, which is what makes the Array(n).fill(v) idiom work: Array(5) produces five empty slots that most array methods skip, and fill() is one of the few methods that writes into holes, turning the array dense in one step.
When to reach for it
Use it to seed a fixed-size buffer (Array(64).fill(0)), to reset a scratch array between iterations without reallocating, or to blank out a slice of a grid row.
What trips people up
- Objects are shared, not copied.
Array(3).fill([])gives three references to one array, so pushing intoarr[0]changes all three. UseArray.from({ length: 3 }, () => [])when each slot needs its own object. - It cannot change the length. Filling an empty array does nothing at all — set
lengthor use theArray(n)constructor first. endis exclusive, and both indices are clamped rather than throwing when out of range.
For a non-mutating single-index change, use with() instead.
Example
When to use it
- Build a zero-initialised counter array with Array(26).fill(0).
- Reset a reusable scratch buffer between loop iterations without allocating a new array.
- Blank out a slice of a grid row with fill(null, 2, 5).
- Turn the empty slots left by Array(n) into a dense array before mapping over it.
Frequently asked questions
How do I create an array of n zeros in JavaScript?
Use Array(n).fill(0) — the constructor makes n empty slots and fill() writes a real value into each one. Array(n) alone leaves holes that map() and forEach() silently skip.
Why does changing one element of a filled array change them all?
Because fill() stores the same reference in every slot when you pass an object or array. Build the values per index with Array.from({length: n}, () => ({})) so each slot gets its own object.
Does fill() modify the original array?
Yes, fill() mutates the array in place and returns that same array, so it throws a TypeError on a frozen array — in strict and sloppy mode alike, because fill() always writes with the throwing form of assignment. A sealed array can still be filled, since sealing keeps existing elements writable. Use with() or toSpliced() when you need a copy instead.
More examples
The shared-object trap
fill() evaluates the object literal once, so all three slots point at it and one write shows up in every element. Array.from() calls the factory per index, so only the first object changes.
const shared = Array(3).fill({ hits: 0 });
shared[0].hits = 1;
console.log(shared);
const independent = Array.from({ length: 3 }, () => ({ hits: 0 }));
independent[0].hits = 1;
console.log(independent);fill() cannot grow an array
Filling an empty array is a no-op because there are no indexes in range. Setting length first creates the slots; out-of-range start values simply select an empty range instead of throwing.
const empty = [];
console.log(empty.fill(1), empty.length);
empty.length = 3;
console.log(empty.fill(1));
// Out-of-range indexes are clamped, not errors
console.log([1, 2, 3].fill(0, 10));Seeding then mapping
map() over Array(4) returns four holes untouched because the callback never runs on empty slots. Filling first makes the array dense so map() visits every index.
// map() skips holes, so fill() first
console.log(Array(4).map((_, i) => i));
console.log(Array(4).fill(null).map((_, i) => i * i));
// keys() also works and skips the intermediate fill
console.log([...Array(4).keys()]);
Discussion