Welcome back! š In the previous lesson, you mastered the for...of loop for iterating over values of arrays and iterables. Now let's explore the final loop in our series ā the for...in loop!
The for...in loop is specifically designed for one job ā iterating over the keys (property names) of an object. Every time you need to inspect, display, or process the properties of an object dynamically, for...in is your tool.
Let's break it down completely!
What is a for...in Loop?
A for...in loop iterates over all the enumerable property keys of an object. Each iteration gives you one key (property name) as a string ā and you can use that key to access the corresponding value.
let person = {
name: "Mihir",
age: 25,
city: "Mumbai",
};
for (let key in person) {
console.log(key, ":", person[key]);
}
// Output:
// name : Mihir
// age : 25
// city : MumbaiSyntax
for (let key in object) {
// use key or object[key]
}keyā a variable that holds the current property name (as a string) on each iterationinā the keyword that separates the variable from the objectobjectā the plain object whose keys you want to loop over
How JavaScript Executes a for...in Loop
let car = {
brand: "Toyota",
model: "Camry",
year: 2023,
color: "White",
};
for (let key in car) {
console.log(`${key} ā ${car[key]}`);
}Step by step:
- Iteration 1:
key = "brand"ācar["brand"]="Toyota" - Iteration 2:
key = "model"ācar["model"]="Camry" - Iteration 3:
key = "year"ācar["year"]=2023 - Iteration 4:
key = "color"ācar["color"]="White" - Done ā no more keys
// Output:
// brand ā Toyota
// model ā Camry
// year ā 2023
// color ā WhiteEach key comes out as a string ā even if the property name looks like a number.
Accessing Keys and Values
Keys Only
let config = {
theme: "dark",
language: "en",
fontSize: 16,
notifications: true,
};
console.log("Config keys:");
for (let key in config) {
console.log(" -", key);
}
// Output:
// Config keys:
// - theme
// - language
// - fontSize
// - notificationsValues Only
console.log("Config values:");
for (let key in config) {
console.log(" -", config[key]);
}
// Output:
// Config values:
// - dark
// - en
// - 16
// - trueKeys and Values Together
console.log("Full config:");
for (let key in config) {
console.log(` ${key}: ${config[key]}`);
}
// Output:
// Full config:
// theme: dark
// language: en
// fontSize: 16
// notifications: trueChecking Own Properties with hasOwnProperty()
When working with objects that may inherit properties from a prototype, use hasOwnProperty() to make sure you only process the object's own properties ā not inherited ones.
let student = {
name: "Priya",
marks: 88,
grade: "B",
};
for (let key in student) {
if (student.hasOwnProperty(key)) {
console.log(`${key}: ${student[key]}`);
}
}
// Output:
// name: Priya
// marks: 88
// grade: BThis is especially important when dealing with objects created from classes or constructors where inherited properties might show up unexpectedly.
Nested Objects
for...in only iterates over the top-level keys of an object. For nested objects, you need another loop inside.
One Level Deep
let employee = {
name: "Rahul",
role: "Developer",
skills: ["JavaScript", "React", "Node.js"],
salary: 75000,
};
for (let key in employee) {
console.log(`${key}: ${employee[key]}`);
}
// Output:
// name: Rahul
// role: Developer
// skills: JavaScript,React,Node.js (array prints as comma-separated)
// salary: 75000Handling Nested Objects
let userProfile = {
name: "Sara",
age: 28,
address: {
city: "Pune",
state: "Maharashtra",
pin: "411001",
},
contact: {
email: "sara@example.com",
phone: "9876543210",
},
};
for (let key in userProfile) {
let value = userProfile[key];
if (typeof value === "object" && !Array.isArray(value)) {
console.log(`${key}:`);
for (let nestedKey in value) {
console.log(` ${nestedKey}: ${value[nestedKey]}`);
}
} else {
console.log(`${key}: ${value}`);
}
}
// Output:
// name: Sara
// age: 28
// address:
// city: Pune
// state: Maharashtra
// pin: 411001
// contact:
// email: sara@example.com
// phone: 9876543210Dynamic Object Inspection
One of the most powerful uses of for...in ā inspecting objects whose structure you don't know in advance.
function inspectObject(obj, label = "Object") {
console.log(`\n=== ${label} ===`);
console.log(`Total properties: ${Object.keys(obj).length}`);
for (let key in obj) {
let value = obj[key];
let type = typeof value;
console.log(` ${key} (${type}): ${value}`);
}
}
let laptop = {
brand: "Dell",
model: "XPS 15",
ram: "16GB",
storage: "512GB",
price: 89999,
inStock: true,
};
inspectObject(laptop, "Laptop Specs");
// Output:
// === Laptop Specs ===
// Total properties: 6
// brand (string): Dell
// model (string): XPS 15
// ram (string): 16GB
// storage (string): 512GB
// price (number): 89999
// inStock (boolean): trueReal-World Examples
Example 1: Display User Settings
let userSettings = {
theme: "dark",
language: "English",
fontSize: 14,
notifications: true,
autoSave: true,
currency: "INR",
};
console.log("āļø Your Current Settings:");
console.log("ā".repeat(35));
for (let setting in userSettings) {
let value = userSettings[setting];
let display = typeof value === "boolean"
? (value ? "ā
Enabled" : "ā Disabled")
: value;
console.log(` ${setting.padEnd(16)}: ${display}`);
}
// Output:
// āļø Your Current Settings:
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
// theme : dark
// language : English
// fontSize : 14
// notifications : ā
Enabled
// autoSave : ā
Enabled
// currency : INRExample 2: Count Object Properties by Type
let product = {
name: "Wireless Headphones",
brand: "Sony",
price: 4999,
rating: 4.5,
inStock: true,
reviews: 1240,
onSale: false,
category: "Electronics",
};
let typeCounts = {};
for (let key in product) {
let type = typeof product[key];
typeCounts[type] = (typeCounts[type] || 0) + 1;
}
console.log("Property Type Summary:");
for (let type in typeCounts) {
console.log(` ${type}: ${typeCounts[type]} property/properties`);
}
// Output:
// Property Type Summary:
// string: 3 property/properties
// number: 3 property/properties
// boolean: 2 property/propertiesExample 3: Compare Two Objects
function compareObjects(obj1, obj2, name1 = "Object 1", name2 = "Object 2") {
let allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
console.log(`\n${"Key".padEnd(15)} | ${name1.padEnd(15)} | ${name2.padEnd(15)} | Match`);
console.log("ā".repeat(65));
for (let key of allKeys) {
let val1 = obj1[key] ?? "ā";
let val2 = obj2[key] ?? "ā";
let match = obj1[key] === obj2[key] ? "ā
" : "ā";
console.log(`${key.padEnd(15)} | ${String(val1).padEnd(15)} | ${String(val2).padEnd(15)} | ${match}`);
}
}
let plan1 = { storage: "10GB", support: "Email", price: 499, api: false };
let plan2 = { storage: "50GB", support: "Priority", price: 999, api: true };
compareObjects(plan1, plan2, "Basic Plan", "Pro Plan");
// Output:
// Key | Basic Plan | Pro Plan | Match
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
// storage | 10GB | 50GB | ā
// support | Email | Priority | ā
// price | 499 | 999 | ā
// api | false | true | āExample 4: Calculate Cart Total from Object
let cart = {
notebook: { price: 120, qty: 3 },
pen: { price: 20, qty: 10 },
eraser: { price: 10, qty: 5 },
ruler: { price: 35, qty: 2 },
};
let grandTotal = 0;
console.log("===== CART SUMMARY =====");
for (let item in cart) {
let { price, qty } = cart[item];
let subtotal = price * qty;
grandTotal += subtotal;
console.log(`${item.padEnd(12)}: ā¹${price} Ć ${qty} = ā¹${subtotal}`);
}
console.log("========================");
console.log(`GRAND TOTAL: ā¹${grandTotal}`);
// Output:
// ===== CART SUMMARY =====
// notebook : ā¹120 Ć 3 = ā¹360
// pen : ā¹20 Ć 10 = ā¹200
// eraser : ā¹10 Ć 5 = ā¹50
// ruler : ā¹35 Ć 2 = ā¹70
// ========================
// GRAND TOTAL: ā¹680Example 5: Build a Summary Report from Data Object
let salesReport = {
January: 45000,
February: 52000,
March: 48000,
April: 61000,
May: 57000,
June: 70000,
};
let total = 0;
let highest = { month: "", amount: 0 };
let lowest = { month: "", amount: Infinity };
for (let month in salesReport) {
let amount = salesReport[month];
total += amount;
if (amount > highest.amount) highest = { month, amount };
if (amount < lowest.amount) lowest = { month, amount };
}
let average = total / Object.keys(salesReport).length;
console.log("=== š Sales Report (H1) ===");
for (let month in salesReport) {
let bar = "ā".repeat(Math.round(salesReport[month] / 5000));
console.log(`${month.padEnd(10)}: ā¹${salesReport[month].toLocaleString().padStart(7)} ${bar}`);
}
console.log("\nš Total Revenue : ā¹" + total.toLocaleString());
console.log("š Monthly Average: ā¹" + Math.round(average).toLocaleString());
console.log(`š Best Month : ${highest.month} (ā¹${highest.amount.toLocaleString()})`);
console.log(`š Lowest Month : ${lowest.month} (ā¹${lowest.amount.toLocaleString()})`);
// Output:
// === š Sales Report (H1) ===
// January : ā¹ 45,000 āāāāāāāāā
// February : ā¹ 52,000 āāāāāāāāāā
// ...
// š Total Revenue : ā¹3,33,000
// š Best Month : June (ā¹70,000)
// š Lowest Month : January (ā¹45,000)for...in vs for...of ā Know the Difference
This is the most important distinction to remember:
let person = { name: "Mihir", age: 25, city: "Mumbai" };
let colors = ["Red", "Green", "Blue"];
// for...in on OBJECT ā gives keys ā
for (let key in person) {
console.log(key); // "name", "age", "city"
}
// for...of on ARRAY ā gives values ā
for (let color of colors) {
console.log(color); // "Red", "Green", "Blue"
}
// ā for...in on ARRAY ā gives string indexes, not values!
for (let key in colors) {
console.log(key); // "0", "1", "2" ā not what you want!
}
// ā for...of on OBJECT ā TypeError: object is not iterable!
for (let val of person) {
console.log(val); // TypeError ā
}| Loop | Use on | Gives you |
|---|---|---|
for...in | Objects ā | Keys (property names) |
for...in | Arrays ā ļø | String indexes ā avoid! |
for...of | Arrays ā | Values |
for...of | Objects ā | TypeError ā not iterable |
Simple rule: for...in ā in an object (keys). for...of ā of an array (values).
Common Mistakes
Mistake 1: Using for...in on an Array
let fruits = ["Apple", "Banana", "Mango"];
// ā Gives string indexes ā not what you want for arrays
for (let key in fruits) {
console.log(key); // "0", "1", "2" ā strings!
console.log(fruits[key]); // Works, but bad practice
}
// ā
Use for...of for arrays
for (let fruit of fruits) {
console.log(fruit); // Apple, Banana, Mango ā
}Mistake 2: Forgetting Keys Are Always Strings
let scores = { 1: "Gold", 2: "Silver", 3: "Bronze" };
for (let key in scores) {
console.log(typeof key); // "string" ā always string, even for number keys!
console.log(key + 1); // "11", "21", "31" ā string concatenation, not addition!
}
// ā
Convert to number when needed
for (let key in scores) {
let rank = Number(key);
console.log(`Rank ${rank}: ${scores[key]}`); // Rank 1: Gold ā
}Mistake 3: Iterating Inherited Properties Unintentionally
function Animal(name) {
this.name = name;
}
Animal.prototype.type = "Mammal"; // Inherited property
let dog = new Animal("Rex");
dog.breed = "Labrador";
// ā for...in picks up inherited "type" property too!
for (let key in dog) {
console.log(key); // "name", "breed", "type" ā "type" is inherited!
}
// ā
Filter with hasOwnProperty
for (let key in dog) {
if (dog.hasOwnProperty(key)) {
console.log(key); // "name", "breed" ā
ā own properties only
}
}Mistake 4: Expecting a Specific Order
let data = { b: 2, a: 1, c: 3 };
// ā ļø for...in order is not always guaranteed for all engines
// For string keys, most modern engines do maintain insertion order ā
// but don't rely on it for logic-critical code
for (let key in data) {
console.log(key); // Usually: b, a, c ā but not guaranteed in all cases
}
// ā
If order matters, use an array or sort explicitly
let sorted = Object.keys(data).sort();
for (let key of sorted) {
console.log(`${key}: ${data[key]}`); // a: 1, b: 2, c: 3 ā
}Practical Exercise
Create a file called for-in-loop.js:
// šÆ For...in Loop Practice
// 1. Student profile display
console.log("=== š§āš Student Profile ===");
let student = {
name: "Mihir",
rollNo: 42,
department: "Computer Science",
semester: 5,
cgpa: 8.7,
isHosteler: true,
backlog: false,
};
for (let field in student) {
let value = student[field];
let display = typeof value === "boolean"
? (value ? "Yes ā
" : "No ā")
: value;
console.log(` ${field.padEnd(14)}: ${display}`);
}
// 2. Find keys with specific value type
console.log("\n=== š Number Properties ===");
let mixedData = {
username: "priya_dev",
age: 26,
score: 94.5,
city: "Bangalore",
isPremium: true,
loginCount: 142,
bio: "Full-stack developer",
};
let numberKeys = [];
for (let key in mixedData) {
if (typeof mixedData[key] === "number") {
numberKeys.push(key);
console.log(` ${key}: ${mixedData[key]}`);
}
}
console.log(`Found ${numberKeys.length} number properties.`);
// 3. Copy and transform an object
console.log("\n=== š° Price List with Tax ===");
let basePrices = {
Laptop: 55000,
Phone: 18000,
Tablet: 25000,
Watch: 8000,
Earbuds: 3500,
};
let taxRate = 0.18; // 18% GST
let finalPrices = {};
for (let item in basePrices) {
finalPrices[item] = Math.round(basePrices[item] * (1 + taxRate));
}
console.log(`${"Item".padEnd(10)} | ${"Base Price".padEnd(12)} | ${"With 18% GST".padEnd(12)}`);
console.log("ā".repeat(40));
for (let item in basePrices) {
console.log(
`${item.padEnd(10)} | ā¹${String(basePrices[item]).padEnd(11)} | ā¹${finalPrices[item]}`
);
}
// 4. Nested object ā Employee directory
console.log("\n=== š„ Employee Directory ===");
let directory = {
E001: { name: "Mihir", dept: "Engineering", salary: 85000 },
E002: { name: "Priya", dept: "Design", salary: 72000 },
E003: { name: "Rahul", dept: "Marketing", salary: 65000 },
E004: { name: "Sara", dept: "Engineering", salary: 91000 },
};
for (let id in directory) {
let emp = directory[id];
console.log(`[${id}] ${emp.name.padEnd(8)} | ${emp.dept.padEnd(14)} | ā¹${emp.salary.toLocaleString()}`);
}Run it:
node for-in-loop.jsExpected Output:
=== š§āš Student Profile ===
name : Mihir
rollNo : 42
department : Computer Science
semester : 5
cgpa : 8.7
isHosteler : Yes ā
backlog : No ā
=== š Number Properties ===
age: 26
score: 94.5
loginCount: 142
Found 3 number properties.
=== š° Price List with Tax ===
Item | Base Price | With 18% GST
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Laptop | ā¹55000 | ā¹64900
Phone | ā¹18000 | ā¹21240
...
=== š„ Employee Directory ===
[E001] Mihir | Engineering | ā¹85,000
[E002] Priya | Design | ā¹72,000Key Takeaways
Congratulations! š You now fully understand the for...in loop ā and with it, you've completed the entire loops series!
ā
for...in iterates over the enumerable keys of an object ā one property name per iteration.
ā
Keys are always strings ā even numeric-looking keys like { 1: "Gold" }.
ā
Use hasOwnProperty() to filter out inherited properties when working with class instances or constructor functions.
ā
Nested objects ā for...in only goes one level deep; nest another loop for nested values.
ā
Never use for...in on arrays ā use for...of or a classic for loop instead.
ā
Order is not guaranteed ā if order matters, sort keys manually with Object.keys().sort().
ā
for...in vs for...of:
for...inā object keysfor...ofā array/iterable values
Best Practices
- ā
Use
for...inonly on plain objects ā never on arrays - ā
Always use
hasOwnProperty()when there's any chance of inherited properties - ā
Use
Object.keys(),Object.values(), orObject.entries()when you need array methods on object data - ā
Remember ā keys are always strings ā convert with
Number(key)when needed - ā
If order matters, sort keys first:
Object.keys(obj).sort() - ā
For nested objects, use a nested
for...inor a recursive function - ā
Prefer
for...ofwithObject.entries()overfor...inin modern code ā it's cleaner - ā Keep the loop body focused ā process one property at a time
š Loops Series Complete!
Amazing work! You've now mastered all five loop types in JavaScript:
| Loop | Best For |
|---|---|
for | Known number of iterations |
while | Condition-driven, unknown count |
do...while | Must run body at least once |
for...of | Values of arrays, strings, iterables |
for...in | Keys of plain objects |
What's Next?
You've completed the entire Loops in JavaScript series ā that's a huge milestone! š
Next up, we move into one of the most important topics in all of JavaScript ā Functions ā ā where you'll learn how to organize, reuse, and scale your code like a professional developer!
Let's keep going! šŖ