Shallow copy of an array
A shallow copy of an array is a new array with its own reference, holding the top-level elements of the original. Primitives are copied by value, while nested objects and arrays are copied by reference, so they stay shared with the original.
Theory
TL;DR
- A shallow copy creates a new array, so
copy === arrisfalseand top-level changes do not touch the original. - The shortest way is the spread syntax:
const copy = [...arr]. arr.slice(),Array.from(arr)and[].concat(arr)do exactly the same thing.- All of them copy the top level only: nested objects and arrays remain shared.
- Replacing a whole element of the copy is safe; mutating a field inside a nested object is not.
- For a deep copy you need
structuredClone(arr)orJSON.parse(JSON.stringify(arr)).
Quick example
const arr = [1, 2, 3];
const copy = [...arr];
console.log(copy); // [1, 2, 3]
console.log(copy === arr); // false (this is a new array)The spread operator
The spread syntax ... expands the elements of an array into a new array literal. It is the most modern and the shortest form, and it is the one an interviewer expects to hear.
const arr = [1, 2, 3];
const copy = [...arr];
console.log(copy); // [1, 2, 3]
console.log(copy === arr); // false (a new array)The copy is still shallow: if the elements were objects, they keep pointing at the same data.
const arr = [{ name: 'Tim' }];
const copy = [...arr];
copy[0].name = 'Alex';
console.log(arr[0].name); // "Alex", because the object is sharedslice(), Array.from() and concat()
slice() with no arguments returns a new array, a copy of the whole source. The approach is old but perfectly reliable:
const arr = [1, 2, 3];
const copy = arr.slice();
console.log(copy); // [1, 2, 3]Array.from() builds a new array out of an iterable or array-like value:
const arr = [1, 2, 3];
const copy = Array.from(arr);
console.log(copy); // [1, 2, 3]It is handy when you want more than a plain copy, for instance a copy with every element transformed:
const doubled = Array.from(arr, x => x * 2); // [2, 4, 6]concat() works because it returns a new array instead of mutating the source:
const arr = [1, 2, 3];
const copy = [].concat(arr);
console.log(copy); // [1, 2, 3]What stays shared
Every method above copies the top level only. If the array holds objects or nested arrays, those are kept by reference.
const arr = [[1, 2], [3, 4]];
const copy = [...arr];
copy[0][0] = 99;
console.log(arr[0][0]); // 99, because the nested array is sharedReplacing a whole element of the copy, on the other hand, leaves the original alone, because you change a slot of the new array rather than the shared object:
copy[0] = [7, 8];
console.log(arr[0]); // [99, 2], the original is unchangedComparison of the options
| Option | Code | Creates a new array | Deep copy |
|---|---|---|---|
| Spread | [...arr] | Yes | No |
slice() | arr.slice() | Yes | No |
Array.from() | Array.from(arr) | Yes | No |
concat() | [].concat(arr) | Yes | No |
The takeaway is simple: to make a shallow copy of an array, write const copy = [...arr];.
Deep copying
When the nested structures have to be copied too, a shallow copy is not enough:
const deep = structuredClone(arr);structuredClone() is built into modern browsers and Node.js, handles Map, Set, Date, typed arrays and circular references, but cannot copy functions. The older trick JSON.parse(JSON.stringify(arr)) is simpler, yet it drops undefined and functions, turns a Date into a string and throws on circular references.
Common mistakes
- Assuming
[...arr]gives a fully independent array: nested objects remain shared. - Confusing copying with assignment:
const copy = arrcreates no array at all, it is the same reference. - Reaching for
JSON.parse(JSON.stringify(arr))on an array withDatevalues or functions and then wondering where the data went. - Believing
slice()mutates the array: it returns a new one, unlikesplice(), which changes the source. - Copying an array with a manual
push()loop where a single spread expression is enough.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.