Welcome back! 👋 In the previous lesson, you mastered JavaScript objects in depth. Now let's explore one of the most useful ES6 features that makes working with both arrays and objects dramatically cleaner — Destructuring!
Destructuring lets you unpack values from arrays or properties from objects into individual variables in a single, clean line. You'll see it in every modern JavaScript codebase — in function parameters, API response handling, React components, and more.
Once you understand destructuring, your code will be noticeably shorter and much more readable. Let's dive in!
What is Destructuring?
Destructuring is a syntax that lets you extract values from arrays or objects and assign them to variables — all in one step.
// Without destructuring — verbose
let user = { name: "Mihir", age: 25, city: "Mumbai" };
let name = user.name;
let age = user.age;
let city = user.city;
// With destructuring — clean and concise ✅
let { name, age, city } = user;
console.log(name); // "Mihir"
console.log(age); // 25
console.log(city); // "Mumbai"Same result — half the code. That's destructuring.
Part 1: Array Destructuring
Array destructuring extracts values based on position (index).
Basic Syntax
let [first, second, third] = array;Basic Example
let fruits = ["Apple", "Banana", "Mango", "Orange"];
let [first, second, third] = fruits;
console.log(first); // "Apple"
console.log(second); // "Banana"
console.log(third); // "Mango"Skip Elements with Commas
Use an empty comma , to skip positions you don't need.
let scores = [92, 85, 78, 60, 55];
let [top, , third] = scores; // Skip index 1
console.log(top); // 92
console.log(third); // 78let colors = ["Red", "Green", "Blue", "Yellow", "Purple"];
let [, , , fourth] = colors; // Skip first three
console.log(fourth); // "Yellow"Default Values
Provide a fallback when the value at that position is undefined.
let [a = 10, b = 20, c = 30] = [1, 2];
console.log(a); // 1 (from array)
console.log(b); // 2 (from array)
console.log(c); // 30 (default — nothing at index 2)let [username = "Guest", role = "viewer"] = ["Mihir"];
console.log(username); // "Mihir" (from array)
console.log(role); // "viewer" (default)Rest Elements ...
Capture remaining elements into a new array.
let [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]let [head, ...tail] = ["Apple", "Banana", "Mango", "Orange"];
console.log(head); // "Apple"
console.log(tail); // ["Banana", "Mango", "Orange"]Swap Variables — Classic Trick
let x = 5;
let y = 10;
// ❌ Old way — needs temp variable
let temp = x;
x = y;
y = temp;
// ✅ Destructuring swap — clean and elegant
[x, y] = [y, x];
console.log(x); // 10
console.log(y); // 5Destructure Function Return Values
function getMinMax(numbers) {
return [Math.min(...numbers), Math.max(...numbers)];
}
let [min, max] = getMinMax([3, 1, 9, 5, 7]);
console.log(`Min: ${min}`); // Min: 1
console.log(`Max: ${max}`); // Max: 9Part 2: Object Destructuring
Object destructuring extracts values based on key name — not position.
Basic Syntax
let { key1, key2, key3 } = object;Basic Example
let user = {
name: "Mihir",
age: 25,
city: "Mumbai",
role: "Admin",
};
let { name, age, city } = user;
console.log(name); // "Mihir"
console.log(age); // 25
console.log(city); // "Mumbai"Rename While Destructuring
Use : to assign to a different variable name.
let user = { name: "Mihir", age: 25 };
// Rename 'name' → 'username', 'age' → 'userAge'
let { name: username, age: userAge } = user;
console.log(username); // "Mihir"
console.log(userAge); // 25
// console.log(name); // ❌ ReferenceError — 'name' doesn't exist hereDefault Values
Provide a fallback when the key doesn't exist or is undefined.
let user = { name: "Mihir", age: 25 };
let { name, age, role = "viewer", city = "Unknown" } = user;
console.log(name); // "Mihir"
console.log(age); // 25
console.log(role); // "viewer" (default — not in object)
console.log(city); // "Unknown" (default — not in object)Rename + Default Values Together
let config = { theme: "dark" };
let {
theme: currentTheme = "light",
fontSize: size = 14,
language: lang = "en",
} = config;
console.log(currentTheme); // "dark" (from object)
console.log(size); // 14 (default)
console.log(lang); // "en" (default)Rest Properties ...
Capture remaining properties into a new object.
let user = { name: "Mihir", age: 25, city: "Mumbai", role: "Admin" };
let { name, age, ...rest } = user;
console.log(name); // "Mihir"
console.log(age); // 25
console.log(rest); // { city: "Mumbai", role: "Admin" }Part 3: Nested Destructuring
Destructure values from deeply nested arrays and objects.
Nested Object Destructuring
let student = {
name: "Mihir",
marks: {
math: 92,
science: 88,
english: 85,
},
address: {
city: "Mumbai",
state: "Maharashtra",
},
};
// Destructure nested properties
let {
name,
marks: { math, science, english },
address: { city, state },
} = student;
console.log(name); // "Mihir"
console.log(math); // 92
console.log science); // 88
console.log(city); // "Mumbai"
console.log(state); // "Maharashtra"Nested Array Destructuring
let matrix = [[1, 2], [3, 4], [5, 6]];
let [[a, b], [c, d], [e, f]] = matrix;
console.log(a, b); // 1 2
console.log(c, d); // 3 4
console.log(e, f); // 5 6Mixed — Object with Arrays Inside
let employee = {
name: "Priya",
skills: ["JavaScript", "React", "Node.js"],
scores: { technical: 92, communication: 88 },
};
let {
name,
skills: [primarySkill, ...otherSkills],
scores: { technical, communication },
} = employee;
console.log(name); // "Priya"
console.log(primarySkill); // "JavaScript"
console.log(otherSkills); // ["React", "Node.js"]
console.log(technical); // 92
console.log(communication); // 88Part 4: Destructuring in Function Parameters
This is where destructuring truly shines in real-world code — pass an object to a function and destructure directly in the parameter list.
Object Parameter Destructuring
// ❌ Old way — access properties one by one inside
function displayUser(user) {
console.log(`${user.name} | ${user.role} | ${user.city}`);
}
// ✅ Destructure in parameter — direct access
function displayUser({ name, role, city }) {
console.log(`${name} | ${role} | ${city}`);
}
displayUser({ name: "Mihir", role: "Admin", city: "Mumbai" });
// Output: Mihir | Admin | MumbaiWith Default Values in Parameters
function createProfile({ name, role = "viewer", active = true, city = "Unknown" }) {
return {
name,
role,
active,
city,
createdAt: new Date().toLocaleDateString(),
};
}
let profile1 = createProfile({ name: "Mihir", role: "admin", city: "Mumbai" });
let profile2 = createProfile({ name: "Priya" }); // uses all defaults
console.log(profile1);
// { name: "Mihir", role: "admin", active: true, city: "Mumbai", createdAt: "..." }
console.log(profile2);
// { name: "Priya", role: "viewer", active: true, city: "Unknown", createdAt: "..." }Array Parameter Destructuring
function getFirstAndLast([first, ...rest]) {
return { first, last: rest[rest.length - 1] };
}
let result = getFirstAndLast([10, 20, 30, 40, 50]);
console.log(result); // { first: 10, last: 50 }Destructure Inside forEach / map
let students = [
{ name: "Mihir", marks: 92, dept: "CS" },
{ name: "Priya", marks: 85, dept: "IT" },
{ name: "Rahul", marks: 78, dept: "CS" },
];
// Destructure each student object directly in the callback
students.forEach(({ name, marks, dept }) => {
console.log(`${name} (${dept}): ${marks} marks`);
});
// Output:
// Mihir (CS): 92 marks
// Priya (IT): 85 marks
// Rahul (CS): 78 marks// Map with destructuring
let summaries = students.map(({ name, marks }) =>
`${name}: ${marks >= 75 ? "Pass ✅" : "Fail ❌"}`
);
console.log(summaries);
// ["Mihir: Pass ✅", "Priya: Pass ✅", "Rahul: Pass ✅"]Part 5: Destructuring with for...of
let users = [
{ name: "Mihir", role: "Admin", active: true },
{ name: "Priya", role: "Editor", active: true },
{ name: "Rahul", role: "Viewer", active: false },
];
for (let { name, role, active } of users) {
console.log(`${active ? "✅" : "❌"} ${name.padEnd(8)} — ${role}`);
}
// Output:
// ✅ Mihir — Admin
// ✅ Priya — Editor
// ❌ Rahul — Viewer// With Object.entries()
let scores = { math: 92, science: 88, english: 85, history: 76 };
for (let [subject, score] of Object.entries(scores)) {
let grade = score >= 90 ? "A" : score >= 75 ? "B" : "C";
console.log(`${subject.padEnd(10)}: ${score} (${grade})`);
}
// Output:
// math : 92 (A)
// science : 88 (B)
// english : 85 (B)
// history : 76 (B)Real-World Examples
Example 1: Process API Response
// Simulated API response
let apiResponse = {
status: 200,
message: "Success",
data: {
user: {
id: 1,
name: "Mihir Shah",
email: "mihir@example.com",
plan: "pro",
stats: {
posts: 42,
followers: 1280,
following: 95,
},
},
token: "eyJhbGciOiJIUzI1NiJ9...",
},
};
// Extract exactly what you need in one destructure
let {
status,
data: {
user: {
name,
email,
plan,
stats: { posts, followers },
},
token,
},
} = apiResponse;
console.log(`Status: ${status}`);
console.log(`User: ${name} (${email})`);
console.log(`Plan: ${plan}`);
console.log(`Posts: ${posts}`);
console.log(`Followers: ${followers}`);
console.log(`Token: ${token.slice(0, 20)}...`);
// Output:
// Status: 200
// User: Mihir Shah (mihir@example.com)
// Plan: pro
// Posts: 42
// Followers: 1280
// Token: eyJhbGciOiJIUzI1N...Example 2: Settings Merge with Defaults
const DEFAULTS = {
theme: "light",
language: "en",
fontSize: 14,
notifications: true,
autoSave: true,
};
function applySettings(userSettings = {}) {
const {
theme = DEFAULTS.theme,
language = DEFAULTS.language,
fontSize = DEFAULTS.fontSize,
notifications = DEFAULTS.notifications,
autoSave = DEFAULTS.autoSave,
} = userSettings;
console.log("Applied Settings:");
console.log(` theme: ${theme}`);
console.log(` language: ${language}`);
console.log(` fontSize: ${fontSize}`);
console.log(` notifications: ${notifications}`);
console.log(` autoSave: ${autoSave}`);
return { theme, language, fontSize, notifications, autoSave };
}
applySettings({ theme: "dark", fontSize: 16 });
// Applied Settings:
// theme: dark
// language: en (default)
// fontSize: 16
// notifications: true (default)
// autoSave: true (default)Example 3: Restructure Data from API
// Raw API data with snake_case keys
let rawUsers = [
{ user_id: 1, first_name: "Mihir", last_name: "Shah", is_active: true, role_id: 1 },
{ user_id: 2, first_name: "Priya", last_name: "Nair", is_active: false, role_id: 2 },
{ user_id: 3, first_name: "Rahul", last_name: "Gupta", is_active: true, role_id: 2 },
];
const ROLES = { 1: "Admin", 2: "Editor" };
// Transform using destructuring + rename
let cleanUsers = rawUsers.map(({
user_id: id,
first_name: firstName,
last_name: lastName,
is_active: isActive,
role_id: roleId,
}) => ({
id,
name: `${firstName} ${lastName}`,
active: isActive,
role: ROLES[roleId],
}));
console.log(cleanUsers);
// [
// { id: 1, name: "Mihir Shah", active: true, role: "Admin" },
// { id: 2, name: "Priya Nair", active: false, role: "Editor" },
// { id: 3, name: "Rahul Gupta", active: true, role: "Editor" },
// ]Example 4: Cart Summary with Destructuring
let cart = [
{ name: "Laptop", price: 55000, qty: 1, discount: 10 },
{ name: "Mouse", price: 800, qty: 2, discount: 0 },
{ name: "Keyboard", price: 1500, qty: 1, discount: 5 },
];
function calcLineTotal({ price, qty, discount }) {
let discounted = price * (1 - discount / 100);
return discounted * qty;
}
console.log("=== 🛒 Cart Summary ===");
let grandTotal = 0;
for (let item of cart) {
let { name, price, qty, discount } = item;
let lineTotal = calcLineTotal(item);
grandTotal += lineTotal;
console.log(
`${name.padEnd(12)} ₹${price} × ${qty}` +
`${discount ? ` (-${discount}%)` : ""}` +
` = ₹${lineTotal.toLocaleString()}`
);
}
console.log(`${"─".repeat(40)}`);
console.log(`TOTAL: ₹${grandTotal.toLocaleString()}`);
// Output:
// Laptop ₹55000 × 1 (-10%) = ₹49,500
// Mouse ₹800 × 2 = ₹1,600
// Keyboard ₹1500 × 1 (-5%) = ₹1,425
// ────────────────────────────────────────
// TOTAL: ₹52,525Destructuring Cheat Sheet
Array Destructuring
// Basic
let [a, b, c] = [1, 2, 3];
// Skip elements
let [a, , c] = [1, 2, 3];
// Default values
let [a = 10, b = 20] = [1];
// Rest elements
let [first, ...rest] = [1, 2, 3, 4, 5];
// Swap variables
[a, b] = [b, a];
// From function return
let [min, max] = getMinMax(array);Object Destructuring
// Basic
let { name, age } = user;
// Rename
let { name: userName } = user;
// Default values
let { role = "viewer" } = user;
// Rename + default
let { role: userRole = "viewer" } = user;
// Rest properties
let { name, ...rest } = user;
// In function params
function fn({ name, age = 0 }) { ... }
// Nested
let { address: { city } } = user;Common Mistakes
Mistake 1: Destructuring undefined or null
let user = null;
// ❌ Cannot destructure null — TypeError!
let { name } = user; // TypeError: Cannot destructure property 'name' of null
// ✅ Use default value or guard
let { name } = user ?? {}; // safe — destructures empty object
let { name } = user || {}; // also common patternMistake 2: Forgetting Curly Braces for Object Destructuring in Standalone Statement
let name, age;
// ❌ JS reads { as a block, not destructuring!
{ name, age } = { name: "Mihir", age: 25 }; // SyntaxError
// ✅ Wrap in parentheses when not using let/const/var
({ name, age } = { name: "Mihir", age: 25 }); // ✅
// ✅ Or just use let/const
let { name, age } = { name: "Mihir", age: 25 }; // ✅Mistake 3: Array Destructuring is Position-Based
let [a, b, c] = [1, 2, 3];
// ❌ You can't skip by name — only by position
let [, , third] = [1, 2, 3]; // must skip with comma
// ✅ If you want named access — use object destructuring instead
let { first, third } = { first: 1, second: 2, third: 3 };Mistake 4: Nested Destructuring — Missing Intermediate Key
let user = { name: "Mihir" }; // No 'address' key
// ❌ Trying to destructure from a key that doesn't exist
let { address: { city } } = user;
// TypeError: Cannot destructure property 'city' of undefined
// ✅ Provide default for the nested object
let { address: { city } = {} } = user;
console.log(city); // undefined — safe ✅Mistake 5: Confusing Rest ... in Arrays vs Objects
// ✅ Rest in array — collects remaining elements into array
let [first, ...others] = [1, 2, 3, 4];
console.log(others); // [2, 3, 4]
// ✅ Rest in object — collects remaining properties into object
let { name, ...details } = { name: "Mihir", age: 25, city: "Mumbai" };
console.log(details); // { age: 25, city: "Mumbai" }
// ❌ Rest must ALWAYS be last
let { ...rest, name } = user; // SyntaxError — rest must be last!Practical Exercise
Create a file called destructuring.js:
// 🎯 Destructuring Practice
// 1. Array destructuring — coordinate system
console.log("=== 📍 Coordinates ===");
let points = [[10, 20], [35, 45], [60, 80]];
for (let [x, y] of points) {
let distance = Math.sqrt(x ** 2 + y ** 2).toFixed(2);
console.log(`Point (${x}, ${y}) → Distance from origin: ${distance}`);
}
// 2. Object destructuring — employee processing
console.log("\n=== 👨💼 Employee Report ===");
let employees = [
{ name: "Mihir", dept: "Engineering", salary: 85000, yrs: 3 },
{ name: "Priya", dept: "Design", salary: 72000, yrs: 5 },
{ name: "Rahul", dept: "Engineering", salary: 91000, yrs: 7 },
{ name: "Sara", dept: "Marketing", salary: 68000, yrs: 2 },
];
let totalSalary = 0;
for (let { name, dept, salary, yrs } of employees) {
let bonus = yrs >= 5 ? salary * 0.15 : salary * 0.08;
let totalComp = salary + bonus;
totalSalary += totalComp;
console.log(
`${name.padEnd(8)} | ${dept.padEnd(14)} | ` +
`₹${salary.toLocaleString().padStart(7)} + ` +
`Bonus ₹${Math.round(bonus).toLocaleString().padStart(6)} = ` +
`₹${Math.round(totalComp).toLocaleString()}`
);
}
console.log(`\nTotal Payroll: ₹${Math.round(totalSalary).toLocaleString()}`);
// 3. Nested destructuring — API response
console.log("\n=== 🌐 API Response Parser ===");
let responses = [
{
status: 200,
data: { user: { name: "Mihir", plan: "pro" }, credits: 500 },
},
{
status: 200,
data: { user: { name: "Priya", plan: "free" }, credits: 100 },
},
{
status: 403,
data: { user: { name: "Guest", plan: "none" }, credits: 0 },
},
];
for (let { status, data: { user: { name, plan }, credits } } of responses) {
let access = status === 200 ? "✅ Allowed" : "❌ Denied";
console.log(`${access} | ${name.padEnd(8)} | Plan: ${plan.padEnd(5)} | Credits: ${credits}`);
}
// 4. Function parameter destructuring — build UI cards
console.log("\n=== 🃏 Product Cards ===");
function renderCard({ name, price, rating = 0, inStock = false, discount = 0 }) {
let finalPrice = discount ? price * (1 - discount / 100) : price;
let stockLabel = inStock ? "🟢 In Stock" : "🔴 Out of Stock";
let priceLabel = discount
? `₹${finalPrice.toLocaleString()} (${discount}% off)`
: `₹${price.toLocaleString()}`;
console.log(`\n📦 ${name}`);
console.log(` Price : ${priceLabel}`);
console.log(` Rating : ${"⭐".repeat(Math.round(rating))} (${rating})`);
console.log(` Status : ${stockLabel}`);
}
let products = [
{ name: "Wireless Headphones", price: 4999, rating: 4.5, inStock: true, discount: 20 },
{ name: "Mechanical Keyboard", price: 6500, rating: 4.2, inStock: false },
{ name: "USB-C Hub", price: 1299, rating: 3.8, inStock: true },
];
products.forEach(renderCard);Run it:
node destructuring.jsExpected Output:
=== 📍 Coordinates ===
Point (10, 20) → Distance from origin: 22.36
Point (35, 45) → Distance from origin: 57.01
Point (60, 80) → Distance from origin: 100.00
=== 👨💼 Employee Report ===
Mihir | Engineering | ₹ 85,000 + Bonus ₹ 6,800 = ₹91,800
Priya | Design | ₹ 72,000 + Bonus ₹ 10,800 = ₹82,800
Rahul | Engineering | ₹ 91,000 + Bonus ₹ 13,650 = ₹1,04,650
Sara | Marketing | ₹ 68,000 + Bonus ₹ 5,440 = ₹73,440
Total Payroll: ₹3,52,690
=== 🌐 API Response Parser ===
✅ Allowed | Mihir | Plan: pro | Credits: 500
✅ Allowed | Priya | Plan: free | Credits: 100
❌ Denied | Guest | Plan: none | Credits: 0
=== 🃏 Product Cards ===
📦 Wireless Headphones
Price : ₹3,999.2 (20% off)
Rating : ⭐⭐⭐⭐⭐ (4.5)
Status : 🟢 In Stock
📦 Mechanical Keyboard
Price : ₹6,500
Rating : ⭐⭐⭐⭐ (4.2)
Status : 🔴 Out of StockKey Takeaways
Congratulations! 🎉 You now fully understand destructuring — one of the most powerful and widely used ES6 features.
✅ Array destructuring — extracts by position. Use commas to skip, ... for rest.
✅ Object destructuring — extracts by key name. Order doesn't matter.
✅ Rename with : — { name: userName } pulls name into a variable called userName.
✅ Default values — { role = "viewer" } or [count = 0] — used when value is undefined.
✅ Rest ... — collects remaining items into array or remaining properties into object. Must always be last.
✅ Nested destructuring — go as deep as you need. Provide = {} defaults for potentially missing nested objects.
✅ Function parameter destructuring — the most common real-world use. Makes function signatures self-documenting.
✅ Use with for...of and array methods — destructure directly in loop variables and callbacks.
Best Practices
- ✅ Use object destructuring for functions with 3+ parameters — much cleaner than positional args
- ✅ Always provide default values for optional destructured properties in function params
- ✅ Use rename + default together for API responses:
{ user_name: name = "Guest" } - ✅ Provide a fallback
= {}when destructuring a potentiallynullorundefinedobject - ✅ Keep nested destructuring to 2 levels max — deeper gets hard to read
- ✅ Use rest
...to cleanly separate known fields from dynamic extras - ✅ Use array destructuring for fixed-position returns like
[error, result]patterns - ✅ Destructure inside
forEach,map, andfor...ofcallbacks — eliminates repetitiveitem.propertyaccess
What's Next?
Excellent work! 🎉 Destructuring is one of those features that once you start using, you'll never want to go back.
Next up, the final lesson in the Working with Data Structures section:
Working with JSON → — the universal data format for every API and web service you'll ever work with. Learn to parse, stringify, validate, and handle JSON like a pro!
Let's keep going! 💪