Array.prototype.copyWithin()
copyWithin(target, start, end) copyWithin() copies a sequence of array elements to another position in the array, overwriting existing values. It mutates the array in place and returns the modified array. This method is useful for moving elements around without creating a new array.
Syntax
arr.copyWithin(target, start, end)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
target | integer | - | Zero-based index where copied elements will be written. Negative indices count from the end. |
start | integer | 0 | Zero-based index to start copying elements from. Negative indices count from the end. |
end | integer | arr.length | Zero-based index to stop copying (exclusive). Negative indices count from the end. |
Examples
Basic usage
const fruits = ["apple", "banana", "cherry", "date", "elderberry"];
fruits.copyWithin(0, 2, 5);
console.log(fruits);
// ["cherry", "date", "elderberry", "date", "elderberry"]
Here copyWithin(0, 2, 5) copies elements at indices 2–4 to position 0, overwriting the first three elements. The original target range is replaced, which is why "date" and "elderberry" appear twice.
Negative indices let you count from the end of the array without knowing its length.
Using negative indices
const nums = [1, 2, 3, 4, 5];
nums.copyWithin(0, -2);
console.log(nums);
// [4, 5, 3, 4, 5]
With copyWithin(0, -2), the source starts two elements from the end (indices 3–4) and writes to position 0. Negative indices resolve against array.length before the copy runs.
Overlapping copies are safe because copyWithin reads the source range before writing to the target.
Overlapping copy
const letters = ["a", "b", "c", "d", "e"];
letters.copyWithin(2, 0, 2);
console.log(letters);
// ["a", "b", "a", "b", "e"]
Because copyWithin captures the source slice before writing, the overlap between source [0,2) and target position 2 does not cause data corruption. The result correctly places "a" and "b" at positions 2 and 3, preserving only the untouched end of the array.
Moving elements to new position
const arr = [1, 2, 3, 4, 5];
arr.copyWithin(3, 0, 2);
console.log(arr);
// [1, 2, 3, 1, 2]
When the target falls within the existing array bounds, copyWithin overwrites existing slots without shifting them. Elements at positions 3 and 4 are replaced while the first three positions stay intact.
If the target index extends past array.length, copyWithin can lengthen the array.
Target beyond array length
const items = ['a', 'b', 'c'];
items.copyWithin(4, 0, 2);
console.log(items);
// ['a', 'b', 'c', empty, 'a', 'b']
Setting the target beyond the array end creates empty slots where the array expands. Those slots are not undefined — they are truly empty and behave differently with iteration methods like map and forEach.
Shifting elements left
const data = [1, 2, 3, 4, 5];
// Copy from index 2 to end, paste at index 0
data.copyWithin(0, 2);
console.log(data);
// [3, 4, 5, 4, 5]
Omitting the end parameter copies from start to the end of the array. Here we copy [3,4,5] to the front, which overwrites the first three slots. The remaining elements at positions 3 and 4 are preserved because the source region (indices 2–4) was captured before writing.
Duplicate array portion
const pattern = [1, 2, 3, 1, 2, 3, 1, 2, 3];
pattern.copyWithin(3, 0, 3);
console.log(pattern);
// [1, 2, 3, 1, 2, 3, 1, 2, 3]
This example copies the first three elements repeatedly, creating a repeating pattern. Since the array length does not change, the final three elements remain from the previous state — the copy fills exactly to position 8.
Common patterns
In-place rotation
function rotate(arr, by) {
const len = arr.length;
if (by >= len) by = by % len;
arr.copyWithin(len, len - by, len);
arr.copyWithin(len - by, 0, len - by);
arr.copyWithin(0, len, len + by);
return arr;
}
console.log(rotate([1, 2, 3, 4, 5], 2)); // [4, 5, 1, 2, 3]
This rotation function uses three copyWithin calls to shift elements without creating a new array. It first copies the tail to a scratch area beyond the array boundary, shifts the body right, then copies the scratch back to the front. This approach works for any typed array as well.
Fill with repeating pattern
const arr = [1, 2, 3, 4, 5, 6];
arr.copyWithin(3, 0, 3);
console.log(arr);
// [1, 2, 3, 1, 2, 3]
How copyWithin() works
copyWithin() reads the source range (start to end) first, then writes the copied values starting at target. Because it captures the values before writing, overlapping source and destination ranges work correctly - you will not read values you just wrote. The method never changes the array’s length: if the copy would extend beyond array.length, it stops at the boundary. Negative indices are resolved against array.length before any processing begins.
Where copyWithin() fits best
copyWithin() is most useful when you want to rearrange data in place and keep the same array object alive. That makes it a good fit for buffer-like workflows, animations, and low-level array manipulation where allocating a fresh array would be unnecessary. Because the method overwrites existing slots, it is usually clearer when you think of the array as a fixed-size window rather than a growing list. If you need insertion or removal instead, splice() is a better match.
Watch out for overwrites
The main hazard with copyWithin() is that it replaces whatever was already at the target position. That is intentional, but it can surprise you if you expect it to insert data instead of replacing it. Before calling it, make sure you know which part of the array will be lost and whether the source range is long enough to fill the destination. In code that manipulates user-visible lists, a small diagram or comment can save a lot of confusion.
Performance characteristics
copyWithin() is designed for typed arrays and binary data. For plain arrays it is no faster than a manual loop, but it is available on all TypedArray variants (Int32Array, Float64Array, etc.) where it can delegate to a fast memmove-style operation inside the JavaScript engine. If you are working with large ArrayBuffer data and need to shift or duplicate regions without allocating a new buffer, copyWithin() is the intended tool.
copyWithin() vs splice() and fill()
copyWithin() differs from splice() in that it never changes the array length - it only overwrites existing slots. It differs from fill() in that it copies values from within the array rather than writing a constant value. Use fill() when you want to write the same value repeatedly; use copyWithin() when you want to duplicate or shift an existing segment.
See Also
- Array.prototype.splice() - Add/remove elements
- Array.prototype.fill() - Fill array with value