|

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
}
PartDescription
keyA variable that takes on each enumerable property name as the loop runs
objectThe object you’re iterating over

Key Characteristics

  1. Enumerates properties — iterates over keys (property names), not values
  2. Only enumerable properties — skips non-enumerable properties (like built-in methods)
  3. Includes prototype chain — also iterates inherited enumerable properties
  4. 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:

  • key takes 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
}
PartDescription
elementA variable that takes on the value of each item
iterableAn object that can be iterated (arrays, strings, maps, sets)

Key Characteristics

  1. Iterates values — gives you the actual values, not keys
  2. Only own values — does not traverse the prototype chain
  3. Works with any iterable — arrays, strings, Maps, Sets, NodeLists, etc.
  4. Cleaner syntax — more readable than classic for loops 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:

  • fruit takes 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?

IterableSupported?
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

Aspectfor...infor...of
Iteration TypeEnumerates over enumerable properties (keys) of an objectIterates directly over the values of iterable objects
Use CasesObjects, arrays (not recommended), strings (returns indices)Arrays, strings, maps, sets, and other iterables
Variable AssignmentProperty names or keysValues of the iterated items
Prototype ChainIncludes properties from the prototype chainExcludes properties from the prototype chain
OrderNot guaranteed for objects; follows insertion order in arrays (ES2015+)Follows the natural iteration order of the iterable

Key Differences

  • for...in is 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...of focuses on iterating over iterable objects where the values are more meaningful than their indices.
  • for...in includes all enumerable properties, including those from the object’s prototype chain. This can lead to unexpected results if not handled carefully.
  • for...of only iterates over the object’s own iterable values and does not traverse up the prototype chain.
  • Using for...in for arrays can make your code less clear because it implies a focus on indices rather than values.
  • for...of clearly 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

Aspectfor...infor...of
Iterates overKeys / property namesValues
Works withObjects (and arrays)Iterables (arrays, strings, Maps, Sets)
Prototype chainIncludes inherited propertiesExcludes inherited properties
Variable getsKey (string)Value
Best forObject propertiesArray/iterable values

What Can Be Iterated with for…of

IterableSupported?
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 propertiesIterating array values
You need keysYou need values
Working with plain objectsWorking with arrays, strings, Maps, Sets
You need both keys and valuesYou 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

PitfallProblemSolution
for...in on arraysIncludes custom propertiesUse for...of
for...of on objectsTypeError — not iterableUse for...in or Object.keys()
Inherited propertiesUnexpected keysFilter with hasOwnProperty()
Modifying during iterationUnpredictable behaviorIterate over a copy
Confusing key vs valueWrong logicRemember: in = key, of = value

Summary

LoopIteratesUse For
for...inKeys (property names)Objects
for...ofValuesArrays, strings, Maps, Sets

Remember:

  • for...in gives you the key (or index as string)
  • for...of gives 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!