Object spread creates a new outer object while retaining references to nested objects. Copy each changed path when the original nested state must remain unchanged.
Reproduce the behavior safely
Run this self-contained fixture in an empty temporary directory, separate from your project. Shell examples create only named fixture files there. JavaScript examples use local values and send no network requests.
const assert = require('node:assert/strict');
const original = {layout: {width: 7}, label: 'sample'};
const shallow = {...original};
assert.notEqual(shallow, original);
assert.equal(shallow.layout, original.layout);
shallow.layout.width = 8;
assert.equal(original.layout.width, 8);
const updated = {...original, layout: {...original.layout, width: 9}};
assert.equal(updated.layout.width, 9);
assert.equal(original.layout.width, 8);
console.log(JSON.stringify({original, updated}));Observed local output
{"original":{"layout":{"width":8},"label":"sample"},"updated":{"layout":{"width":9},"label":"sample"}}Why the result changes
A different outer identity does not establish independence for every descendant. The fixture deliberately changes a shared nested field before demonstrating a path copy, so the original ends at eight, not its initial seven. Compare references at the exact level that changes. This is especially relevant when separate UI states or default configuration objects retain the same nested value.
Choose and verify the correction
Identify the fields you intend to update, copy their containing objects, and leave unrelated branches shared when that is intentional. For an array of records, copy the array and the changed record rather than assuming an array spread copies every record. If data needs a complete independent snapshot, choose a clone operation compatible with its actual types and test it separately. Serialization through JSON is not a general deep-copy contract.
Limits and next checks
Spread copies enumerable own properties; it does not preserve every prototype, descriptor or private state. The example covers plain data objects and a single nested path. const prevents reassignment of its binding but does not freeze nested data. Freeze policies and framework state rules require separate decisions. The verification here concerns mutation ownership rather than a promise about every class instance.
Related: Includes Returns False for a Similar Object: Match the Intended Identity.
Isolated fixture executed on macOS on November 10, 2026 (KST), with v26.5.0. The observed output verifies this example, not every application or runtime.