Primitive vs Reference Types
Key Learning Objectives
Distinguish between JavaScript primitive types and reference types in V8 engine memory.
Understand stack allocation for primitive values vs heap allocation for objects.
Predict mutation side effects when multiple variables reference the same heap object.
Recognize why reassigning an object reference parameter does not mutate the caller argument.
The Interview Problem
What is printed to the console when the following JavaScript code executes, and why does mutating a property behave differently than reassigning the parameter?
1let primitiveVal = 42;2let objA = { count: 1 };3let objB = objA;45function update(num, target) {6 num = 100;7 target.count = 5;8 target = { count: 999 };9}1011update(primitiveVal, objA);1213console.log(primitiveVal, objA.count, objB.count);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
42 5 5
100 5 5
42 999 999
42 5 1
V8 Engine Execution Trace
Step 1 of 8 (Line 1)Allocate primitive value 42 in the global execution context stack frame.
Deep Technical Breakdown
Core Mental Model: Pass by Value vs Pass by Reference Value
JavaScript has 7 primitive types (string, number, bigint, boolean, undefined, symbol, null) and 1 composite reference type (Object, which includes Functions and Arrays).
- Primitives are Immutable and Stored by Value: When a primitive is assigned to another variable or passed to a function, a distinct copy of the bit-level value is pushed onto the stack. Changing one variable never influences another.
- Objects are Stored in the Heap and Accessed by Pointer: When
objB = objAruns, no new object is created in memory. Instead, both variables contain a pointer to the same heap location. Mutatingtarget.count = 5traverses the pointer and mutates the heap memory directly. - Reassignment Breaks the Link: When
target = { count: 999 }executes, it overwrites the local pointer intargetwith the memory address of a freshly allocated object. It does not overwrite the memory address stored inobjAorobjB.
Common Traps & Mistakes
Assuming `const` prevents object mutation. `const` only prevents variable reassignment; properties can still be modified.
Confusing parameter reassignment with mutation. Reassigning a function parameter has zero effect on the caller's reference.
Using shallow cloning (`{ ...obj }` or `Object.assign`) for deeply nested structures where nested objects are still shared references.
FAANG Follow-Up Probes
Probe #1
How does `structuredClone()` differ from `JSON.parse(JSON.stringify(obj))` when copying complex data structures?
Probe #2
Why does `Object.freeze()` only create a shallow freeze, and how would you implement a recursive `deepFreeze` utility?
Probe #3
How does V8 optimize small integers (Smi) and heap numbers under the hood?
