Advanced Object Concepts
- This lesson covers advanced object-oriented concepts in JavaScript.
Introduction to Advanced Object Concepts
In earlier lessons, we learned:
What objects are
How to create and access objects
Object properties and methods
As applications grow larger, how we handle objects becomes extremely important.
Poor object handling can lead to:
Bugs
Unexpected data changes
Difficult debugging
Poor code quality
In this lesson, we will cover advanced and professional object concepts that every JavaScript developer must know.
Topics covered:
Shallow vs Deep Copy
Spread Operator with Objects
Immutability in Objects
Clean Object Design
Shallow vs Deep Copy
What is Copying an Object ?
Copying an object means creating a new object based on an existing object.
There are two types of copying:
Shallow Copy
Deep Copy
Understanding the difference is critical.
Shallow Copy
Definition
A shallow copy copies only the top-level properties of an object.
If the object contains nested objects, the nested object is shared, not duplicated.
Shallow Copy using Spread Operator
Copies top-level properties while nested objects remain shared references.
// Shallow copy example
let user = {
name: "Amit",
address: {
city: "Delhi"
}
};
let copyUser = { ...user };
copyUser.name = "Rahul"; // changes only copy
copyUser.address.city = "Mumbai"; // affects original (shared reference)
console.log(user.name); // Amit
console.log(user.address.city); // Mumbai
Explanation
name is copied independently
address is a reference to the same object
Changing nested data affects both objects
This is the main drawback of shallow copy.
Ways to Create Shallow Copy
Spread operator { ...obj }
Object.assign()
Ways to Create Shallow Copy
Uses spread operator or Object.assign to copy top-level properties only.
// Using Object.assign for shallow copy
let oldObj = {
name: "Amit",
address: {
city: "Delhi"
}
};
let newObj = Object.assign({}, oldObj);
// Modify values
newObj.name = "Rahul";
newObj.address.city = "Mumbai"; // affects original (shared reference)
console.log(oldObj.name); // Amit
console.log(oldObj.address.city); // Mumbai
Deep Copy
Definition
A deep copy creates a completely independent copy, including all nested objects.
Changes in the copied object do not affect the original object.
Deep Copy using JSON Method
Creates a fully independent copy including nested objects.
// Deep copy example
let user = {
name: "Amit",
address: {
city: "Delhi"
}
};
let deepCopy = JSON.parse(JSON.stringify(user));
deepCopy.address.city = "Mumbai";
console.log(user.address.city); // Delhi
console.log(deepCopy.address.city); // Mumbai
Explanation
Entire object structure is duplicated
No shared references
Safer for complex data
Limitations of JSON Deep Copy
Cannot copy functions
Loses undefined values
Not suitable for Date, Map, Set
Shallow vs Deep Copy
Feature Shallow Copy Deep Copy Nested objects Shared Fully copied Safety Risky Safe Performance Faster Slower Use case Simple objects Complex objects Spread Operator with Objects
What is Spread Operator ?
The spread operator (...) expands object properties into a new object.
It is widely used for:
Copying objects
Merging objects
Updating object properties
Basic Object Copy with Spread
Creates a new object by copying properties using the spread operator.
// Copy object using spread
let user = {
name: "Amit",
age: 25
};
let newUser = { ...user };
console.log(newUser);
- This creates a shallow copy.
Updating Object with Spread
Overrides specific properties while copying the rest of the object.
// Updating properties using spread
let user = {
name: "Amit",
age: 25
};
let updatedUser = {
...user,
age: 26
};
console.log(updatedUser); // { name: "Amit", age: 26 }
Original object remains unchanged.
Merging Objects Using Spread
Merging Objects with Spread
Combines multiple objects into a single object using spread syntax.
// Merging objects using spread
let personal = { name: "Amit" };
let contact = { email: "amit@gmail.com" };
let profile = { ...personal, ...contact };
console.log(profile); // { name: "Amit", email: "amit@gmail.com" }
- Spread Operator with Nested Objects
Shallow Copy with Nested Objects
Copies object but nested objects remain shared references.
// Spread with nested object (shallow copy)
let user = {
name: "Amit",
address: {
city: "Delhi"
}
};
let copy = { ...user };
// Changing nested value
copy.address.city = "Mumbai";
console.log(user.address.city); // Mumbai (same reference)
This is still a shallow copy.
Nested objects are shared.
Immutability in Objects
What is Immutability ?
Immutability means not changing the original object, but instead creating a new modified copy.
Why is Immutability Important ?
Prevents unexpected bugs
Makes debugging easier
Improves code predictability
Essential in modern frameworks
Mutable vs Immutable Object Update
Shows bad (direct mutation) vs good (creating new object) practice
// Mutable Example (Bad Practice)
let user = { name: "Amit" };
user.name = "Rahul"; // original object modified
// Immutable Example (Good Practice)
let user = { name: "Amit" };
let newUser = { ...user, name: "Rahul" }; // new object created
- Original object remains unchanged.
Immutability with Nested Objects
Demonstrates updating nested objects without modifying the original object
let user = {
name: "Amit",
address: {
city: "Delhi"
}
};
let updatedUser = {
...user,
address: {
...user.address,
city: "Mumbai"
}
};
This ensures full immutability.
Benefits of Immutability
Easy change tracking
Reliable state management
Better testing
Cleaner architecture
Clean Object Design
What is Clean Object Design ?
Clean object design means creating objects that are:
Easy to read
Easy to maintain
Easy to extend
Free from unnecessary complexity
Principles of Clean Object Design
Use Meaningful Property Names
Clean Object Design with Meaningful Property Names
Improves code readability by using clear and descriptive property names
// Bad
let u = { n: "Amit" };
// Good
let user = { name: "Amit" };
- Keep Objects Focused (Single Responsibility)
Keep Objects Focused with Single Responsibility Principle
Ensures each object handles only one responsibility for better maintainability
// Bad
let user = {
name: "Amit",
calculateSalary() {},
sendEmail() {}
};
// Good
let user = { name: "Amit" };
let salaryService = {};
let emailService = {};
- Avoid Deep Nesting
Reduce Complexity by Flattening Object Structure
Makes code easier to read by avoiding deeply nested object paths
// Bad
user.data.profile.details.address.city
Prefer simpler structure where possible.
Use Consistent Structure
All objects of the same type should follow the same structure.
Do Not Mutate Shared Objects
Always use immutable updates for shared data.
Updating Nested Object Data Without Mutation
Demonstrates a clean way to update nested properties using immutability
function updateUserCity(user, newCity) {
return {
...user,
address: {
...user.address,
city: newCity
}
};
}
This approach is:
Safe
Predictable
Reusable
Common Mistakes
Confusing shallow copy with deep copy
Accidentally mutating objects
Overusing deep nesting
Using unclear property names
Best Practices Summary
Prefer immutability
Understand copy types clearly
Use spread operator carefully
Keep objects clean and focused
Avoid unnecessary mutations