Objects, Arrays & Reference Semantics
Key Learning Objectives
Differentiate between primitive values stored on the stack and composite references stored on the heap.
Understand reference equality (===) versus structural equality.
Master shallow copying mechanisms (Object.assign, object spread) and recognize shared nested reference traps.
Learn safe deep cloning techniques including structuredClone() and its limitations with functions and DOM nodes.
The Interview Problem
What is logged to the console when the following code executes, and how do object aliasing and shallow copying affect nested property mutation?
1const original = {2 id: 1,3 tags: ['js', 'web'],4 meta: { views: 100 },5};67const shallowCopy = { ...original };8const alias = original;910shallowCopy.id = 2;11shallowCopy.tags.push('v8');12shallowCopy.meta.views += 50;1314alias.id = 3;1516const res1 = original.id;17const res2 = original.tags.length;18const res3 = original.meta.views;19const res4 = original === shallowCopy;20const res5 = original.meta === shallowCopy.meta;2122console.log(res1, res2, res3, res4, res5);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
3 3 150 false true
1 2 100 false false
3 2 100 true true
2 3 150 false true
V8 Engine Execution Trace
Step 1 of 9 (Line 1)Global Execution Context allocates original in heap memory at HeapRef#1. Its properties tags (HeapRef#2) and meta (HeapRef#3) are allocated as separate nested heap entities.
Deep Technical Breakdown
Reference Semantics & Heap Aliasing in JavaScript
- Stack vs Heap Storage: In V8, primitive types are allocated on the stack. Objects, arrays, and functions are allocated dynamically on the heap. When an object is assigned to a variable (
const alias = original), only the memory pointer is copied. Both variables now alias the exact same heap block. Any mutation through either identifier mutates the underlying heap entity immediately. - Shallow Copying Mechanics:
- Methods like
{ ...original },Object.assign({}, original),arr.slice(), and[...arr]produce shallow copies. - Top-level primitive values are duplicated onto the new object's shape.
- Any property holding a reference type (nested object, array, date) has its pointer copied by value. The new object points to the same nested heap structures.
- Methods like
- Deep Cloning Alternatives:
structuredClone(obj): The modern ECMAScript standard for deep cloning. Handles nested structures, cyclical references, Maps, Sets, and Dates, but throwsDataCloneErroron functions, DOM nodes, and symbols.JSON.parse(JSON.stringify(obj)): Legacy workaround. Breaks onundefined,NaN,Date(converted to string),RegExp,Map,Set, and throws on circular references.- Recursive custom cloning: Traverses own enumerable properties while tracking visited references in a
WeakMapto support cycles.
Common Traps & Mistakes
Assuming `{ ...state }` in React or Redux deeply isolates nested data. Mutating a nested array inside a shallow-cloned state mutates previous state snapshots and bypasses change detection.
Using `Object.freeze()` expecting deep immutability. `Object.freeze()` is strictly shallow; nested properties can still be mutated.
Comparing two objects with identical keys and values using `===` and expecting `true`. Two distinct objects in memory will always yield `false` under `===`.
FAANG Follow-Up Probes
Probe #1
How does structuredClone() handle circular object references, and why does it fail on functions and DOM nodes?
Probe #2
How would you implement a recursive deepClone function in JavaScript that handles circular references using WeakMap?
Probe #3
Why does React rely on shallow equality comparisons in React.memo and useMemo, and how does shared nested mutation break memoization?
