Assigning an object to another variable does not copy it. Both names refer to the same object. If you edit a property through one name, reading through the other sees that change. This explains many surprising bugs in lists of records.
The spread syntax { ...original } makes a new object by copying its properties. [...items] similarly makes a new array. Later properties override earlier ones: { ...original, done: true } copies the original properties and then replaces done with true. Reversing that order lets the copied done value win instead.
Both copies are shallow: nested objects remain shared. Our study records contain only strings, numbers, and booleans, so a shallow copy is enough when making a revised record.
Do not call everything immutable just because you used const. It protects the binding—the name’s association with a value. It does not freeze an object. Decide whether your program should edit the original object or create a revised copy, and explain that choice. On Day 4 you will put these decisions inside functions.
Predict before running
Which assignment changes original? After running, explain why copy has a different duration. Try adding a nested object only as an extra experiment; notice that spread will not copy that nested object for you.
const original = { topic: "Loops", minutes: 20 };
const alias = original;
alias.minutes = 30;
const copy = { ...original };
copy.minutes = 45;
console.log(original.minutes);
console.log(copy.minutes);Check your prediction
30
45Trace each statement in order. If your prediction differed, describe the first place your mental model and the result diverged before trying again.
A shallow copy still shares nested objects
A spread copies the outer container, not everything reachable from it. If a property holds another object, both copies hold a reference to that nested object. Copy the nested object too when you need to change it independently.
This example uses a preferences record containing a reminder record. Draw two outer boxes and one shared inner box before running; then draw the additional inner box made for independent.
const original = { reminder: { hour: 9 } };
const shallow = { ...original };
shallow.reminder.hour = 10;
console.log(original.reminder.hour);
const independent = { ...original, reminder: { ...original.reminder } };
independent.reminder.hour = 11;
console.log(original.reminder.hour);
console.log(independent.reminder.hour);Check your prediction
10
10
11The first copy shares reminder. The second explicitly makes a new reminder object before changing hour.
Equality asks about identity for objects
Two separately created objects with identical properties are not strictly equal. The comparison asks whether they are the same object, not whether their contents match. For a small test, compare the specific properties you care about. Later you can learn a test framework’s deep-equality tools.
Predict on paper: const a = { score: 1 }; const b = a; const c = { score: 1 }; Which of a === b and a === c is true? Run your experiment, then change b.score and inspect all three. State whether you intended a shared update or an independent value before choosing your copying technique.
For now, practise copying our flat records: their properties hold strings, numbers, and booleans rather than other objects. The nested example explains a limit of spread; you do not need to memorize a technique for copying every possible structure.
A shallow copy does not copy nested records
A spread creates a new outer record or array. It copies the references stored inside it, so nested objects can still be shared. To isolate a nested update, copy every object along the path you intend to change. Do not call a shallow copy an independent snapshot of all data.
Use identity comparisons to ask whether two names refer to the same object, and value comparisons to ask what data it contains. These are different questions. A useful update can allocate a new outer container while intentionally retaining unchanged records.
const before = { topic: "Loops", detail: { minutes: 20 } };
const shallow = { ...before };
shallow.detail.minutes = 30;
console.log(before.detail.minutes);
console.log(shallow === before);
console.log(shallow.detail === before.detail);Check your prediction
30
false
true The outer records differ, but both detail fields point to one nested record. Changing that nested record is visible through either outer record.
const before = { topic: "Loops", detail: { minutes: 20 } };
const after = { ...before, detail: { ...before.detail, minutes: 30 } };
console.log(before.detail.minutes);
console.log(after.detail.minutes);
console.log(after.detail === before.detail);Check your prediction
20
30
false There are now two detail records. This is an explicit two-level copy for this shape, not a general deep-copy algorithm. More complicated data needs a deliberate ownership policy.
Try the rule on new inputs
Try a nested list as well as a nested object. Draw boxes and arrows for both examples before changing data. Identify the exact object that must be copied to preserve the original minutes.
Your turn
References & Copies: practise
Make a completed copy of a session while leaving the original incomplete. Print false, then true. Do not mutate the original.
const session = { topic: "Arrays", minutes: 25, done: false };
// Create completed, then print both done properties.Hint 1: the idea
You need a new object, not another name for the same one.
Hint 2: a first step
Spread session into a new object and write done: true after the spread.
Show one solution
const session = { topic: "Arrays", minutes: 25, done: false };
const completed = { ...session, done: true };
console.log(session.done);
console.log(completed.done);false
trueLater properties override earlier ones. Writing done: true before the spread would let the original false overwrite your change.
What you should be able to explain
- What exactly is copied by spread?
- Draw the shared nested reference in the example.
- Why does identical-looking content not guarantee object equality?
Completion is saved in this browser only. It does not measure mastery.