A spread copy creates a new array but retains references to its elements. Independence of the container is different from independence of nested objects. Choose the depth of copying from the data you intend to change.
Step-by-step walkthrough
Step 1: Locate the changed branch
Draw the references before writing an update. The array owns element references; each element may own another object. Decide whether the requested edit changes the container, an element, or a deeper value. This determines which identities must be replaced.
Step 2: Copy only the necessary path
Create a new outer array and a new object for the changed record. Keep other records shared when their content is unchanged. This gives consumers a useful identity signal without duplicating the entire graph or mutating another owner’s data.
Step 3: Verify ownership explicitly
Compare references as well as displayed values. The edited record should differ by identity, the untouched record can remain identical, and the original value must remain unchanged. These three observations explain structural sharing more clearly than calling everything a deep copy.
Worked scenario
Given const a = [{score: 1}] and const b = [...a], assigning b[0].score = 2 also changes a[0].score. Replacing b[0] with a new object does not replace a[0].
const original = [{id: 1, score: 10}, {id: 2, score: 20}];
const updated = original.map(item =>
item.id === 1 ? {...item, score: 11} : item
);
console.log(original[0].score); // 10
console.log(updated[0].score); // 11
console.log(original === updated); // false
console.log(original[1] === updated[1]); // trueWalk through the example
The map creates a distinct container. Only the matching record is spread into a new object, so its score changes independently. The second record is deliberately shared. If the edited score were nested inside another object, that nested object would also need replacement along the changed path.
Common mistake
JSON serialization is not a universal deep copy: it changes or rejects several value types. structuredClone supports many built-ins but cannot clone functions.
Verify the behavior
Test edits to the first and last records, a missing ID and a nested field. Assert that the input remains unchanged. Decide whether a missing ID returns an unchanged reference or a new equivalent array; either policy should be deliberate and documented.
Interview exercise
How would you update one score while preserving the original array and object?
Answer and reasoning
Map the array and spread only the changed object. Structural sharing preserves untouched references while the modified branch gets a new identity.
Follow-up discussion
Would structuredClone be simpler? It can copy supported graphs, but copying everything loses intentional structural sharing and may reject unsupported values. Choose it for genuinely independent snapshots, not automatically for every UI edit. Is sharing a bug? Sharing unchanged immutable data is useful; sharing data that another owner mutates unexpectedly is the problem.
Continue learning
Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.