JavaScript 14 🧬 loops part 2
In Part 1, we covered for, while, and do...while loops. In Part 2, we’ll explore two more specialized loops: for...in (for object properties) and for...of (for iterable values).
A Quick Look at the Examples
// 1. for...in — iterate object properties
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
};
for (let key in person) {
console.log(key, person[key]);
}
// firstName John
// lastName Doe
// age 30
// 2. for...in with arrays (not recommended)
const arr = ["apple", "banana", "cherry"];
arr.property = "customProperty";
for (let key in arr) {
console.log(key, arr[key]);
}
// 0 apple
// 1 banana
// 2 cherry
// property customProperty
// 3. for...of — iterate array values
const fruits = ['apple', 'banana', 'cherry'];
for (let fruit of fruits) {
console.log(fruit);
}
// apple
// banana
// cherry
// 4. for...of with strings
const greeting = 'Hello';
for (let char of greeting) {
console.log(char);
}
// H
// e
// l
// l
// o
// 5. for...of with Map
const map = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
for (let [key, value] of map) {
console.log(key, value);
}
// a 1
// b 2
// c 3
// 6. for...of with Set
const set = new Set(['apple', 'banana', 'cherry']);
for (let item of set) {
console.log(item);
}
// apple
// banana
// cherry
a. The for...in Loop
The for...in loop is used to iterate over the enumerable properties of an object. It’s particularly useful when you want to access all keys or property names of an object.
Syntax
for (let key in object) {
// some code
}
| Part | Description |
|---|---|
key | A variable that takes on each enumerable property name as the loop runs |
object | The object you’re iterating over |
Key Characteristics
- Enumerates properties — iterates over keys (property names), not values
- Only enumerable properties — skips non-enumerable properties (like built-in methods)
- Includes prototype chain — also iterates inherited enumerable properties
- Iteration order:
- First: numeric keys in ascending order
- Then: string keys in insertion order
- Finally: symbol keys
Example 1: Iterating Object Properties
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
};
for (let key in person) {
console.log(key, person[key]);
}
// firstName John
// lastName Doe
// age 30
How it works:
keytakes on each property name:"firstName","lastName","age"person[key]accesses the value using bracket notation- Output shows each key-value pair
Example 2: for…in with Arrays (Not Recommended)
const arr = ["apple", "banana", "cherry"];
arr.property = "customProperty";
for (let key in arr) {
console.log(key, arr[key]);
}
// 0 apple
// 1 banana
// 2 cherry
// property customProperty
⚠️ Warning: for...in iterates over all enumerable properties, including custom ones added to the array. This is why it’s generally better to use classic for loops or .forEach() for arrays.
Handling Prototype Chain
for...in includes inherited properties — use hasOwnProperty() to filter:
const person = { name: "Alice", age: 30 };
// Add a property to Object.prototype (not recommended!)
Object.prototype.customProp = "inherited";
for (let key in person) {
console.log(key); // name, age, customProp
}
// Filter with hasOwnProperty()
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key); // name, age
}
}
b. The for...of Loop
The for...of loop is used to iterate directly over iterable objects such as arrays, strings, maps, sets, etc. It provides a more concise and readable way to traverse these collections.
Syntax
for (let element of iterable) {
// code block executed for each element
}
| Part | Description |
|---|---|
element | A variable that takes on the value of each item |
iterable | An object that can be iterated (arrays, strings, maps, sets) |
Key Characteristics
- Iterates values — gives you the actual values, not keys
- Only own values — does not traverse the prototype chain
- Works with any iterable — arrays, strings, Maps, Sets, NodeLists, etc.
- Cleaner syntax — more readable than classic
forloops for simple iteration
Example 1: Iterating an Array
const fruits = ['apple', 'banana', 'cherry'];
for (let fruit of fruits) {
console.log(fruit);
}
// apple
// banana
// cherry
How it works:
fruittakes on each value in the array- No need for index access — cleaner than
for (let i = 0; ...)
Example 2: Iterating a String
const greeting = 'Hello';
for (let char of greeting) {
console.log(char);
}
// H
// e
// l
// l
// o
Note: Strings are iterable — for...of gives you each character.
Example 3: Iterating a Map
const map = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
for (let [key, value] of map) {
console.log(key, value);
}
// a 1
// b 2
// c 3
Note: Maps return [key, value] pairs — destructuring makes it clean.
Example 4: Iterating a Set
const set = new Set(['apple', 'banana', 'cherry']);
for (let item of set) {
console.log(item);
}
// apple
// banana
// cherry
Note: Sets only contain values (no duplicates) — for...of gives you each unique value.
What Can Be Iterated?
| Iterable | Supported? |
|---|---|
| Array | ✅ Yes |
| String | ✅ Yes |
| Map | ✅ Yes |
| Set | ✅ Yes |
| NodeList | ✅ Yes |
| arguments object | ✅ Yes |
| Generator | ✅ Yes |
Plain Object {} | ❌ No — use for...in |
| Number | ❌ No |
// This will throw an error
const obj = { a: 1, b: 2 };
// for (let value of obj) { } // ❌ TypeError: obj is not iterable
c. for...in vs for...of
| Aspect | for...in | for...of |
|---|---|---|
| Iteration Type | Enumerates over enumerable properties (keys) of an object | Iterates directly over the values of iterable objects |
| Use Cases | Objects, arrays (not recommended), strings (returns indices) | Arrays, strings, maps, sets, and other iterables |
| Variable Assignment | Property names or keys | Values of the iterated items |
| Prototype Chain | Includes properties from the prototype chain | Excludes properties from the prototype chain |
| Order | Not guaranteed for objects; follows insertion order in arrays (ES2015+) | Follows the natural iteration order of the iterable |
Key Differences
for...inis designed to iterate over the properties of an object, making it suitable for objects themselves or arrays when you need access to index keys.for...offocuses on iterating over iterable objects where the values are more meaningful than their indices.for...inincludes all enumerable properties, including those from the object’s prototype chain. This can lead to unexpected results if not handled carefully.for...ofonly iterates over the object’s own iterable values and does not traverse up the prototype chain.- Using
for...infor arrays can make your code less clear because it implies a focus on indices rather than values. for...ofclearly conveys that you intend to iterate over the values of an iterable collection, enhancing readability.
When to Use Which
Use for...in:
- When iterating over object properties (including their keys)
- If you need both keys and values from objects (though this is less common with arrays)
Use for...of:
- When iterating over arrays, strings, maps, sets, or other iterable collections where the actual values are of primary interest
- For cleaner, more predictable code when working with iterables
Complete Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Loops — Part 2</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f8f9fa;
color: #333;
line-height: 1.6;
}
h1 { color: #007bff; border-bottom: 3px solid #007bff; padding-bottom: 10px; }
h2 { color: #28a745; border-left: 4px solid #28a745; padding-left: 15px; margin-top: 30px; }
.demo-box {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin: 15px 0;
}
pre {
background: #1e1e1e;
color: #d4d4d4;
padding: 15px;
border-radius: 8px;
overflow-x: auto;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
line-height: 1.8;
}
.keyword { color: #569cd6; }
.string { color: #ce9178; }
.number { color: #b5cea8; }
.function { color: #dcdcaa; }
.comment { color: #6a9955; }
.boolean { color: #569cd6; }
#output {
background: #e9ecef;
padding: 15px;
border-radius: 8px;
margin-top: 15px;
min-height: 40px;
font-family: 'Courier New', monospace;
font-size: 0.85rem;
border-left: 4px solid #007bff;
white-space: pre-wrap;
}
table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
text-align: left;
}
th { background: #007bff; color: white; }
tr:nth-child(even) { background: #f8f9fa; }
.btn {
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 6px;
font-size: 1em;
font-weight: bold;
cursor: pointer;
margin: 5px;
transition: all 0.3s;
}
.btn:hover {
background: #0056b3;
transform: translateY(-2px);
}
.btn-success { background: #28a745; }
.btn-success:hover { background: #1e7e34; }
</style>
</head>
<body>
<h1>Loops — Part 2</h1>
<div class="demo-box">
<h2>1. for...in — Object Properties</h2>
<pre>
<span class="keyword">const</span> person = {
firstName: <span class="string">"John"</span>,
lastName: <span class="string">"Doe"</span>,
age: <span class="number">30</span>,
};
<span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> person) {
console.log(key, person[key]);
}
<span class="comment">// firstName John
// lastName Doe
// age 30</span>
</pre>
</div>
<div class="demo-box">
<h2>2. for...in with Arrays (Not Recommended)</h2>
<pre>
<span class="keyword">const</span> arr = [<span class="string">"apple"</span>, <span class="string">"banana"</span>, <span class="string">"cherry"</span>];
arr.property = <span class="string">"customProperty"</span>;
<span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> arr) {
console.log(key, arr[key]);
}
<span class="comment">// 0 apple
// 1 banana
// 2 cherry
// property customProperty</span>
</pre>
<p class="note">⚠️ Notice how <code>for...in</code> also picks up the custom <code>property</code> key!</p>
</div>
<div class="demo-box">
<h2>3. for...of — Array Values</h2>
<pre>
<span class="keyword">const</span> fruits = [<span class="string">'apple'</span>, <span class="string">'banana'</span>, <span class="string">'cherry'</span>];
<span class="keyword">for</span> (<span class="keyword">let</span> fruit <span class="keyword">of</span> fruits) {
console.log(fruit);
}
<span class="comment">// apple
// banana
// cherry</span>
</pre>
</div>
<div class="demo-box">
<h2>4. for...of — Strings</h2>
<pre>
<span class="keyword">const</span> greeting = <span class="string">'Hello'</span>;
<span class="keyword">for</span> (<span class="keyword">let</span> char <span class="keyword">of</span> greeting) {
console.log(char);
}
<span class="comment">// H
// e
// l
// l
// o</span>
</pre>
</div>
<div class="demo-box">
<h2>5. for...of — Map and Set</h2>
<pre>
<span class="keyword">const</span> map = <span class="keyword">new</span> <span class="function">Map</span>([
[<span class="string">'a'</span>, <span class="number">1</span>],
[<span class="string">'b'</span>, <span class="number">2</span>],
]);
<span class="keyword">for</span> (<span class="keyword">let</span> [key, value] <span class="keyword">of</span> map) {
console.log(key, value);
}
<span class="keyword">const</span> set = <span class="keyword">new</span> <span class="function">Set</span>([<span class="string">'apple'</span>, <span class="string">'banana'</span>]);
<span class="keyword">for</span> (<span class="keyword">let</span> item <span class="keyword">of</span> set) {
console.log(item);
}
</pre>
</div>
<div class="demo-box">
<h2>6. for...in vs for...of Comparison</h2>
<table>
<tr>
<th>Aspect</th>
<th>for...in</th>
<th>for...of</th>
</tr>
<tr>
<td><strong>Iterates over</strong></td>
<td>Keys / property names</td>
<td>Values</td>
</tr>
<tr>
<td><strong>Works with</strong></td>
<td>Objects (and arrays)</td>
<td>Iterables (arrays, strings, Maps, Sets)</td>
</tr>
<tr>
<td><strong>Prototype chain</strong></td>
<td>Includes inherited properties</td>
<td>Excludes inherited properties</td>
</tr>
<tr>
<td><strong>Best for</strong></td>
<td>Object properties</td>
<td>Array/iterable values</td>
</tr>
</table>
</div>
<div class="demo-box">
<h2>7. Interactive: Iterate Your Choice</h2>
<button class="btn" onclick="showObjectIteration()">for...in — Object</button>
<button class="btn btn-success" onclick="showArrayIteration()">for...of — Array</button>
<div id="interactiveOutput"></div>
</div>
<div class="demo-box">
<h2>8. Live Output — All Examples</h2>
<div id="output">Loading...</div>
</div>
<script>
// ============================================
// Loops — Part 2 — Live Demo
// ============================================
let results = [];
// 1. for...in — Object properties
results.push('📌 for...in — Object Properties:\n');
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
};
for (let key in person) {
results.push(' ' + key + ': ' + person[key]);
}
results.push('');
// 2. for...in — Array (includes custom properties)
results.push('📌 for...in — Array (includes custom props):\n');
const arr = ["apple", "banana", "cherry"];
arr.property = "customProperty";
for (let key in arr) {
results.push(' ' + key + ': ' + arr[key]);
}
results.push(' ⚠️ Notice the custom "property" key is included!');
results.push('');
// 3. for...of — Array values
results.push('📌 for...of — Array Values:\n');
const fruits = ['apple', 'banana', 'cherry'];
for (let fruit of fruits) {
results.push(' ' + fruit);
}
results.push('');
// 4. for...of — String characters
results.push('📌 for...of — String Characters:\n');
const greeting = 'Hello';
let chars = [];
for (let char of greeting) {
chars.push(char);
}
results.push(' "Hello" → [' + chars.join(', ') + ']');
results.push('');
// 5. for...of — Map
results.push('📌 for...of — Map Entries:\n');
const map = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
for (let [key, value] of map) {
results.push(' ' + key + ' → ' + value);
}
results.push('');
// 6. for...of — Set
results.push('📌 for...of — Set Values:\n');
const set = new Set(['apple', 'banana', 'cherry', 'apple']); // duplicate ignored
for (let item of set) {
results.push(' ' + item);
}
results.push(' (Note: "apple" duplicate was ignored)');
results.push('');
// 7. for...in vs for...of on the same array
results.push('📌 Same Array, Different Loops:\n');
const mixed = ['a', 'b', 'c'];
let inResult = [];
for (let key in mixed) {
inResult.push(key);
}
results.push(' for...in gives: [' + inResult.join(', ') + '] (indices as strings)');
let ofResult = [];
for (let value of mixed) {
ofResult.push(value);
}
results.push(' for...of gives: [' + ofResult.join(', ') + '] (actual values)');
results.push('');
// 8. for...in with prototype chain
results.push('📌 for...in and Prototype Chain:\n');
const obj = { a: 1, b: 2 };
Object.prototype.inheritedProp = "inherited";
let inheritedKeys = [];
for (let key in obj) {
inheritedKeys.push(key);
}
results.push(' for...in keys: [' + inheritedKeys.join(', ') + '] (includes inherited)');
let ownKeys = [];
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
ownKeys.push(key);
}
}
results.push(' Own keys only: [' + ownKeys.join(', ') + '] (filtered with hasOwnProperty)');
delete Object.prototype.inheritedProp; // cleanup
results.push('');
// 9. Practical: Sum with for...of
results.push('📌 Practical: Sum with for...of:\n');
const numbers = [10, 20, 30, 40, 50];
let sum = 0;
for (let num of numbers) {
sum += num;
}
results.push(' [' + numbers.join(', ') + '] → sum = ' + sum);
results.push('');
// 10. Practical: Object to array of entries
results.push('📌 Practical: Object Entries:\n');
const user = { name: "Alice", age: 30, role: "Admin" };
let entries = [];
for (let key in user) {
entries.push(key + '=' + user[key]);
}
results.push(' ' + entries.join(' | '));
document.getElementById('output').textContent = results.join('\n');
// ============================================
// Interactive Functions
// ============================================
function showObjectIteration() {
const output = document.getElementById('interactiveOutput');
const car = {
brand: "Toyota",
model: "Corolla",
year: 2020,
color: "blue"
};
let html = '<strong>for...in — Object Properties:</strong><br>';
for (let key in car) {
html += ` ${key}: ${car[key]}<br>`;
}
output.innerHTML = html;
}
function showArrayIteration() {
const output = document.getElementById('interactiveOutput');
const colors = ['red', 'green', 'blue', 'yellow'];
let html = '<strong>for...of — Array Values:</strong><br>';
for (let color of colors) {
html += ` 🎨 ${color}<br>`;
}
output.innerHTML = html;
}
</script>
</body>
</html>
Quick Reference
for…in vs for…of
| Aspect | for...in | for...of |
|---|---|---|
| Iterates over | Keys / property names | Values |
| Works with | Objects (and arrays) | Iterables (arrays, strings, Maps, Sets) |
| Prototype chain | Includes inherited properties | Excludes inherited properties |
| Variable gets | Key (string) | Value |
| Best for | Object properties | Array/iterable values |
What Can Be Iterated with for…of
| Iterable | Supported? |
|---|---|
| Array | ✅ Yes |
| String | ✅ Yes |
| Map | ✅ Yes |
| Set | ✅ Yes |
| NodeList | ✅ Yes |
| arguments | ✅ Yes |
Plain Object {} | ❌ No |
| Number | ❌ No |
When to Use Which
Use for...in when… | Use for...of when… |
|---|---|
| Iterating object properties | Iterating array values |
| You need keys | You need values |
| Working with plain objects | Working with arrays, strings, Maps, Sets |
| You need both keys and values | You want clean, readable code |
Best Practices
✅ Do This:
// Use for...of for arrays
for (const fruit of fruits) {
console.log(fruit);
}
// Use for...in for objects
for (const key in person) {
console.log(key, person[key]);
}
// Filter inherited properties with hasOwnProperty
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key);
}
}
// Use Object.keys() instead of for...in for objects
Object.keys(person).forEach(key => {
console.log(key, person[key]);
});
// Destructure Map entries
for (const [key, value] of map) {
console.log(key, value);
}
❌ Don’t Do This:
// Don't use for...in for arrays
for (const i in arr) {
console.log(arr[i]); // Works, but not recommended
}
// Don't use for...of on plain objects
const obj = { a: 1 };
// for (const val of obj) { } // ❌ TypeError: obj is not iterable
// Don't forget hasOwnProperty when needed
for (const key in obj) {
console.log(key); // May include inherited props
}
// Don't modify the object while iterating
for (const key in obj) {
delete obj[key]; // Unpredictable behavior
}
// Don't confuse the two
for (const x in arr) { } // x is INDEX
for (const x of arr) { } // x is VALUE
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
for...in on arrays | Includes custom properties | Use for...of |
for...of on objects | TypeError — not iterable | Use for...in or Object.keys() |
| Inherited properties | Unexpected keys | Filter with hasOwnProperty() |
| Modifying during iteration | Unpredictable behavior | Iterate over a copy |
| Confusing key vs value | Wrong logic | Remember: in = key, of = value |
Summary
| Loop | Iterates | Use For |
|---|---|---|
for...in | Keys (property names) | Objects |
for...of | Values | Arrays, strings, Maps, Sets |
Remember:
for...ingives you the key (or index as string)for...ofgives you the value
Pro Tip: Use for...of for arrays, strings, Maps, and Sets — it gives you the actual values and is more readable. Use for...in only for object properties — and always filter with hasOwnProperty() if you don’t want inherited properties. For objects, consider using Object.keys(), Object.values(), or Object.entries() with .forEach() — it’s cleaner and more predictable than for...in. And remember: for...of cannot iterate plain objects — they’re not iterable!
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!