Lesson 27: Mastering JavaScript Object references and copying with challenges!

JavaScript stores primitive values (string, number, boolean, null, undefined, symbol, bigint) as actual values. But when you work with objects (including arrays and functions), JavaScript stores references to memory addresses, not the object itself.
So:
let a = { name: "Alice" };
let b = a;
b.name = "Bob";
console.log(a.name); // "Bob" — same object!
a
andb
point to the same object.Cloning objects incorrectly leads to bugs with shared state, side effects, or unexpected mutations.
🔍 2. Fill Any Gaps
Let’s fill in advanced and nuanced gaps 👇
🔸 Reference Identity vs. Value Equality
{} === {} // false (different references)
Even structurally identical objects are never equal unless same reference.
🔸 const
Doesn’t Freeze Objects
const obj = { a: 1 };
obj.a = 2; // ✅ Allowed
obj = { b: 2 }; // ❌ TypeError
const
locks the binding, not the content of the object.
🔸 Shallow vs Deep Copy — A Trap
let obj = { info: { age: 20 } };
let clone = Object.assign({}, obj);
obj.info.age = 30;
console.log(clone.info.age); // 30! 😱
Nested references are still shared — only one level is copied with Object.assign
.
🔸 Object.assign Pitfall: null
and undefined
are ignored
Object.assign({}, null, undefined, { a: 1 }); // ✅ { a: 1 }
🔸 Spread Operator ≠ Deep Clone
let user = { nested: { x: 1 } };
let copy = { ...user };
user.nested.x = 99;
console.log(copy.nested.x); // 99 😱
🔸 structuredClone
Only in Modern Browsers
✅ Supports circular refs
❌ Does not support functions, DOM nodes, class instances
🔸 JSON-based cloning trap:
JSON.parse(JSON.stringify(obj));
✅ Works for most primitives
❌ Loses functions,
undefined
,Symbol
, circular refs
🔸 Lodash’s cloneDeep
handles almost all cases
import _ from 'lodash';
_.cloneDeep(obj);
💪 3. Challenge Me Deeply
🟢 Basic (1–3)
Create two variables pointing to the same object. Modify one, show that the change reflects in both.
Use
Object.assign()
to copy an object with a nested object. Change the nested property and prove the copy is shallow.Write a function
shallowClone(obj)
that replicatesObject.assign({}, obj)
behavior.
🟡 Intermediate (4–7)
Create a function that merges multiple user setting objects into a target using
Object.assign
.Clone an object with a function property using JSON-based method. Explain what happens.
Use spread syntax to "clone" an object and demonstrate it failing with a nested object.
Create an object with a circular reference. Try to JSON.stringify it. What happens?
🔴 Advanced (8–10)
Write a recursive function
deepClone(obj)
that handles nested plain objects and arrays.Use
structuredClone
to copy an object containing dates, maps, sets, and circular refs. Show it works.Benchmark performance difference between
structuredClone
,JSON
, and_.cloneDeep
on a large object.
🎯 Bonus Brain-Twister
- You have two objects with identical structure, one deeply cloned and the other shallow-cloned. Can you mutate a nested property so only one reflects the change? Prove and explain.
💼 4. Interview-Ready Questions
🧠 Conceptual
What does “copy by reference” mean in JavaScript?
Explain shallow vs deep cloning.
How does
Object.assign
differ from the spread operator?
🔎 Debugging Scenario
function update(obj) {
obj.name = "Updated";
}
let a = { name: "Original" };
update(a);
console.log(a.name); // Why is this “Updated”?
📌 Real-World Pitfall
You passed a configuration object into a library and it unexpectedly changed your original object. Why?
✅ Best Practices
Clone inputs in utility functions before mutating.
Use
structuredClone
or_.cloneDeep
when in doubt.Treat objects as immutable where possible (especially in React/Redux).
🚫 Red Flags in Interviews
Using JSON clone on objects with functions or circular refs
Believing spread syntax does deep clone
Not knowing about shallow vs deep copy distinction
🌍 5. Real-World Usage
🔸 In React
- Immutable state updates require copying objects:
setUser(prev => ({ ...prev, name: "New" }));
🔸 In Redux
- Reducers must return new object references for changes to trigger re-renders.
🔸 In GraphQL/Apollo
- Cache normalization and merging require deep cloning and deduplication of normalized records.
🔸 Libraries
immer
: handles immutable updates via proxies[
lodash
]:_.cloneDeep
,_.merge
,_.isEqual
[
structuredClone
]: native deep clone with circular ref support
🧠 6. Remember Like a Pro
✨ Analogy
Think of objects like Google Docs links — copying the link (reference) doesn’t give you a new file.
🧩 Mnemonic
"POUR" → Primitives are Owned, Objects Use References
📊 Cheatsheet (Shallow vs Deep Clone)
Method | Deep? | Functions? | Circular? | Notes |
Object.assign | ❌ | ✅ | ❌ | One-level only |
{ ...obj } | ❌ | ✅ | ❌ | Shallow only |
JSON.stringify/parse | ❌ | ❌ | ❌ | Loses undefined , Symbol |
structuredClone | ✅ | ❌ | ✅ | Built-in, fast, limited types |
_.cloneDeep | ✅ | ✅ | ✅ | Handles most cases well |
🧩 7. Apply It in a Fun Way
🛠️ Mini Project: “Settings Preset Editor”
🧩 An app that lets users:
Choose a preset (object)
Edit it
Clone and customize it without affecting original
Steps:
Define preset templates as object literals
Allow cloning via:
Shallow copy (
Object.assign
)Deep copy (
structuredClone
)
Use a UI to toggle between versions
Log and compare references and values
Visualize JSON differences (maybe use
deep-diff
)
➕ Bonus Extension:
Add undo/redo functionality using snapshot cloning
Store clones in
localStorage
for persistence
🧠 Optional - Extra Value
🔧 Open Source Projects Using This:
React (immutable state)
Redux Toolkit
Lodash
Immer
Svelte (uses reactivity based on reference changes)
🪤 Common Dev Mistakes:
Mutating props/state directly
Using shallow clone where deep clone is needed
Forgetting about nested objects in context of clone
⚡ Performance Tips
Prefer
structuredClone
over_.cloneDeep
where available — much fasterUse shallow clone if you control the structure and don’t need deep copy
Subscribe to my newsletter
Read articles from manoj ymk directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
