1. Courses
  2. Developer Foundations
  3. JavaScript Deep Dive
  4. Stop 3

35 minIntermediate

Objects, arrays and references

When you assign an object, JavaScript does not copy it. It copies a reference, so two names can point at the same order and a change through one shows up in the other. This lesson shows the mechanism, the copy tools and their limits, and the immutable update style React and Redux depend on.

By the end you can

  • Explain why b = a copies a number but shares an object
  • Tell mutation from reassignment, and say what const and Object.freeze really protect
  • Choose between spread, structuredClone and an immutable update for a nested order
  • Reproduce and fix the "I edited the copy and the original changed" bug, with a test that catches it

The everyday picture

The storeroom at the back of a store has one door. If the store manager gives a second staff member a duplicate key, there are now two keys and still one storeroom. When one of them takes out five cartons of cooking oil, the other opens the door and finds five fewer. Nobody "copied the stock". They share it.

Compare that with photocopying the stock count sheet. Each person gets their own paper. Writing "40" on your copy changes nothing on mine. But look closely at the sheet: the last line says "detailed lines: see the blue folder on shelf 3". The photocopy says that too, and there is still only one blue folder. Both of us can open it and write in it. That is a shallow copy, the source of most bugs in this lesson.

Values and references

A variable holds one small thing. For a primitive (JavaScript in one sitting), that thing is the value itself: 1250, 'S014', true. For an object, the object lives in a separate area of memory called the , and the variable holds a to it, like an address. Assignment always copies what is in the variable. For a primitive that is the value. For an object it is the address, so you get a second key to the same room.

JavaScript
let a = 1250;
let b = a;                        // copies the value
b = 990;
console.log(a, b);

const order = { id: 'ORD-5512', totalCents: 2500 };
const sameOrder = order;          // copies the reference, not the object
sameOrder.totalCents = 0;
console.log(order.totalCents);
console.log(order === sameOrder);
Output
1250 990
0
true

The same rule applies when you call a function. The parameter receives a copy of whatever the caller passed: a copy of a number, or a copy of a reference. So a function that changes properties of an object it was given is changing the caller's object. This is sometimes called "pass by sharing".

Quick check

function markPaid(order) { order.status = 'PAID'; } is called as markPaid(myOrder). What is myOrder.status afterwards?

Variables Heap: objects a 1250 b 990 a primitive's value sits in the variable itself, so b = a made a copy order sameOrder reference one Order id: 'ORD-5512' totalCents: 0 set via sameOrder
Primitives live in the variable, so b = a makes an independent copy. An object lives in the heap; order and sameOrder hold two references to the same one, so setting totalCents through either name changes the only order there is.

Loading the rest of the lesson…