What happens: Objects are stored by reference, not by value (unlike primitives)
Reference vs Value Copying:
1. Primitives - copied by value
javascript
let a = "hello";
let b = a; // copies the actual value
a = "world";
console.log(b); // "hello" (independent copy)2. Objects - copied by reference
javascript
let user = { name: "John" };
let admin = user; // copies the reference, not the object
admin.name = "Pete";
console.log(user.name); // "Pete" (same object!)Key Reference Behaviors:
1. Multiple variables point to same object
javascript
let obj1 = { value: 5 };
let obj2 = obj1;
let obj3 = obj1;
obj2.value = 10;
console.log(obj1.value); // 10 (all point to same object)
console.log(obj3.value); // 102. Object comparison compares references
javascript
let a = { name: "John" };
let b = { name: "John" }; // different objects
let c = a; // same reference
console.log(a == b); // false (different objects)
console.log(a === b); // false (different objects)
console.log(a == c); // true (same reference)
console.log(a === c); // true (same reference)3. const objects can be modified
javascript
const user = { name: "John" };
user.name = "Pete"; // ✅ Works - modifying property
user.age = 30; // ✅ Works - adding property
// user = {}; // ❌ Error - can't reassign the referenceObject Cloning Methods:
1. Shallow copy with Object.assign()
javascript
let user = { name: "John", age: 30 };
// Method 1: Object.assign
let clone1 = Object.assign({}, user);
// Method 2: Spread operator
let clone2 = { ...user };
clone1.name = "Pete";
console.log(user.name); // "John" (original unchanged)2. Problem with nested objects (shallow copy issue)
javascript
let user = {
name: "John",
address: { city: "NYC" }
};
let clone = { ...user };
clone.address.city = "LA";
console.log(user.address.city); // "LA" (nested object still shared!)3. Deep copy with structuredClone()
javascript
let user = {
name: "John",
address: { city: "NYC" }
};
let clone = structuredClone(user);
clone.address.city = "LA";
console.log(user.address.city); // "NYC" (truly independent!)Interview Gotchas:
javascript
// Gotcha 1: Object comparison
let a = {};
let b = {};
console.log(a === b); // false (different objects!)
// Gotcha 2: Function parameters
function changeName(obj) {
obj.name = "Changed";
obj = { name: "New Object" }; // doesn't affect original
}
let user = { name: "John" };
changeName(user);
console.log(user.name); // "Changed" (not "New Object")
// Gotcha 3: Array of objects
let users = [{ name: "John" }, { name: "Jane" }];
let copy = [...users]; // shallow copy!
copy[0].name = "Pete";
console.log(users[0].name); // "Pete" (objects still shared!)
// Gotcha 4: const with nested objects
const data = { user: { name: "John" } };
data.user.name = "Pete"; // ✅ Works
data.user = { name: "New" }; // ✅ Works (changing property)
// data = {}; // ❌ Error (reassigning const)
// Gotcha 5: structuredClone limitations
structuredClone({
func: function() {}, // ❌ Error - can't clone functions
date: new Date(), // ✅ Works
regex: /abc/ // ✅ Works
});Quick Decision Tree:
- Need independent copy? → Use cloning
- Nested objects? → Use
structuredClone() - Simple objects? → Use
{...obj}orObject.assign() - Has functions? → Manual cloning or accept shallow copy
Bottom line: Objects share references! Use === to check if same object, cloning methods to create independent copies. Watch out for nested objects in shallow copies!
How Object Parameters Work in Functions:
When you pass an object to a function:
- The reference gets copied (not the object itself)
- The parameter becomes a local variable that holds a copy of the reference
- Both the original variable and parameter point to the same object
Visual Explanation:
javascript
let user = { name: "John" }; // user holds reference to object
function changeName(obj) { // obj gets a COPY of the reference
// Now both 'user' and 'obj' point to the SAME object
obj.name = "Changed"; // ✅ Modifies the shared object
obj = { name: "New Object" }; // ❌ Only changes local 'obj' reference
}
changeName(user);What happens step by step:
javascript
// Step 1: Before function call
user → { name: "John" } // user points to object
// Step 2: Function call - reference is copied
user → { name: "John" } ← obj // both point to same object
// Step 3: obj.name = "Changed"
user → { name: "Changed" } ← obj // still same object, property modified
// Step 4: obj = { name: "New Object" }
user → { name: "Changed" }
obj → { name: "New Object" } // obj now points to different object
// Step 5: Function ends, obj is destroyed
user → { name: "Changed" } // original reference unchangedSimple Rule:
You can modify the object’s properties, but you cannot change what the original variable points to
javascript
function test(obj) {
// ✅ These work - modifying the shared object
obj.name = "New Name";
obj.age = 25;
delete obj.city;
// ❌ This doesn't affect original - reassigning local reference
obj = { completely: "different" };
}
let user = { name: "John" };
test(user);
console.log(user); // { name: "New Name", age: 25 } - properties changed!More Examples:
javascript
// Example 1: Property modification
function addAge(person) {
person.age = 30; // ✅ Modifies shared object
}
let user = { name: "John" };
addAge(user);
console.log(user); // { name: "John", age: 30 }
// Example 2: Reassignment doesn't work
function replaceUser(person) {
person = { name: "Pete", age: 25 }; // ❌ Only changes local reference
}
let user = { name: "John" };
replaceUser(user);
console.log(user); // { name: "John" } - unchanged!
// Example 3: Arrays work the same way
function addItem(arr) {
arr.push("new"); // ✅ Modifies shared array
arr = [1, 2, 3]; // ❌ Only changes local reference
}
let myArray = ["a", "b"];
addItem(myArray);
console.log(myArray); // ["a", "b", "new"]Bottom line: Function parameters get a copy of the reference, so you can modify the object’s contents but can’t change what the original variable points to
