JavaScript has two modern loop types specifically designed for iteration: for...of for iterating over values (arrays, strings, etc.) and for...in for iterating over object properties. These loops are cleaner and more intuitive than traditional for loops for many common tasks. Let's master modern JavaScript iteration!
For...of Loop
The for...of loop iterates over the values of iterable objects like arrays, strings, sets, and maps.
Basic Syntax
for (let value of iterable) {
// Use value directly
}
// Example with array
let fruits = ["apple", "banana", "orange"];
for (let fruit of fruits) {
console.log(fruit);
}
// Output:
// apple
// banana
// orangeWhy Use For...of?
Cleaner syntax for iterating values
Traditional For Loop
// Traditional for loop
let fruits = ["apple", "banana", "orange"];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
// More verbose
// Need to manage index
// More room for errorsFor...of Loop
// Modern for...of loop
let fruits = ["apple", "banana", "orange"];
for (let fruit of fruits) {
console.log(fruit);
}
// Cleaner and simpler
// Direct access to values
// No index management neededUse for...of when:
- You need the values, not indices
- Iterating arrays, strings, sets, maps
- You want clean, readable code
- You don't need to modify the array
For...of with Arrays
Iterating Array Values
let numbers = [10, 20, 30, 40, 50];
// Get values directly
for (let num of numbers) {
console.log(num);
}
// Output: 10, 20, 30, 40, 50
// Process each value
let doubled = [];
for (let num of numbers) {
doubled.push(num * 2);
}
console.log(doubled); // [20, 40, 60, 80, 100]
// Sum array
let sum = 0;
for (let num of numbers) {
sum += num;
}
console.log("Sum:", sum); // 150
// Find values
let words = ["hello", "world", "javascript", "loops"];
for (let word of words) {
if (word.length > 5) {
console.log(word); // "javascript"
}
}Getting Index with entries()
let fruits = ["apple", "banana", "orange"];
// Get both index and value
for (let [index, fruit] of fruits.entries()) {
console.log(`${index}: ${fruit}`);
}
// Output:
// 0: apple
// 1: banana
// 2: orange
// Using destructuring
let colors = ["red", "green", "blue"];
for (let [i, color] of colors.entries()) {
console.log(`Color ${i + 1} is ${color}`);
}
// Output:
// Color 1 is red
// Color 2 is green
// Color 3 is blueNested Arrays
// Array of arrays
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// Iterate outer array
for (let row of matrix) {
console.log(row); // Each sub-array
}
// Iterate all elements
for (let row of matrix) {
for (let num of row) {
console.log(num); // Individual numbers
}
}
// With destructuring
let people = [
["John", 25],
["Jane", 30],
["Bob", 35]
];
for (let [name, age] of people) {
console.log(`${name} is ${age} years old`);
}
// Output:
// John is 25 years old
// Jane is 30 years old
// Bob is 35 years oldFor...of with Strings
Strings are iterable! You can loop through each character.
let text = "Hello";
// Iterate characters
for (let char of text) {
console.log(char);
}
// Output: H, e, l, l, o
// Count specific characters
let message = "JavaScript is awesome!";
let count = 0;
for (let char of message) {
if (char === 'a' || char === 'A') {
count++;
}
}
console.log("'a' appears", count, "times"); // 3
// Build new string
let original = "hello";
let reversed = "";
for (let char of original) {
reversed = char + reversed; // Prepend each char
}
console.log(reversed); // "olleh"
// Check for vowels
let word = "education";
let vowels = "aeiou";
let vowelCount = 0;
for (let char of word) {
if (vowels.includes(char.toLowerCase())) {
vowelCount++;
}
}
console.log("Vowels:", vowelCount); // 5For...of with Other Iterables
Sets
// Sets are iterable
let uniqueNumbers = new Set([1, 2, 3, 4, 5]);
for (let num of uniqueNumbers) {
console.log(num);
}
// Output: 1, 2, 3, 4, 5
// Remove duplicates and iterate
let items = [1, 2, 2, 3, 3, 4];
let unique = new Set(items);
for (let item of unique) {
console.log(item); // 1, 2, 3, 4 (no duplicates)
}Maps
// Maps are iterable
let userRoles = new Map([
["john", "admin"],
["jane", "editor"],
["bob", "viewer"]
]);
// Iterate entries [key, value]
for (let [username, role] of userRoles) {
console.log(`${username}: ${role}`);
}
// Output:
// john: admin
// jane: editor
// bob: viewer
// Iterate just keys
for (let username of userRoles.keys()) {
console.log(username);
}
// Iterate just values
for (let role of userRoles.values()) {
console.log(role);
}Iterable objects: Arrays, strings, sets, maps, typed arrays, and more. Objects are NOT iterable by default (use for...in instead).
For...in Loop
The for...in loop iterates over the enumerable properties (keys) of an object.
Basic Syntax
for (let key in object) {
// Use key to access properties
console.log(key, object[key]);
}
// Example
let person = {
name: "John",
age: 30,
city: "New York"
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// Output:
// name: John
// age: 30
// city: New YorkIterating Object Properties
let user = {
username: "john_doe",
email: "john@example.com",
age: 25,
isActive: true
};
// Get all keys and values
for (let key in user) {
console.log(`${key}: ${user[key]}`);
}
// Count properties
let propCount = 0;
for (let key in user) {
propCount++;
}
console.log("Properties:", propCount); // 4
// Create array of keys
let keys = [];
for (let key in user) {
keys.push(key);
}
console.log(keys); // ["username", "email", "age", "isActive"]
// Create array of values
let values = [];
for (let key in user) {
values.push(user[key]);
}
console.log(values); // ["john_doe", "john@example.com", 25, true]Modern Alternative: Object Methods
let person = {
name: "Alice",
age: 28,
city: "London"
};
// Object.keys() - array of keys
for (let key of Object.keys(person)) {
console.log(key); // name, age, city
}
// Object.values() - array of values
for (let value of Object.values(person)) {
console.log(value); // Alice, 28, London
}
// Object.entries() - array of [key, value] pairs
for (let [key, value] of Object.entries(person)) {
console.log(`${key}: ${value}`);
}
// Output:
// name: Alice
// age: 28
// city: LondonModern approach: Use Object.keys(), Object.values(), or Object.entries() with for...of instead of for...in for cleaner code.
For...in with Arrays (Don't!)
While for...in technically works with arrays, you shouldn't use it for arrays. Use for...of instead.
let fruits = ["apple", "banana", "orange"];
// DON'T: for...in with arrays
for (let index in fruits) {
console.log(typeof index); // "string"!
console.log(fruits[index]);
}
// Problems:
// 1. Index is a STRING, not number
// 2. Can include inherited properties
// 3. Order not guaranteed
// 4. Slower than for...of
// DO: for...of with arrays
for (let fruit of fruits) {
console.log(fruit); // Direct access to values
}
// Or traditional for loop with index
for (let i = 0; i < fruits.length; i++) {
console.log(i, fruits[i]); // i is a NUMBER
}Important: Don't use for...in with arrays! Use for...of for values or traditional for loop for indices. for...in is for objects.
For vs For...of vs For...in
| Loop Type | Best For | Returns |
|---|---|---|
for | Arrays (with index) | Index (number) |
for...of | Arrays, strings, iterables | Values |
for...in | Objects | Keys/property names |
let colors = ["red", "green", "blue"];
let person = { name: "John", age: 30 };
// FOR loop - arrays with index
console.log("=== for loop ===");
for (let i = 0; i < colors.length; i++) {
console.log(i, colors[i]); // 0 red, 1 green, 2 blue
}
// FOR...OF - array values
console.log("\n=== for...of ===");
for (let color of colors) {
console.log(color); // red, green, blue
}
// FOR...IN - object properties
console.log("\n=== for...in ===");
for (let key in person) {
console.log(key, person[key]); // name John, age 30
}
// Modern: Object.entries() with for...of
console.log("\n=== Object.entries() ===");
for (let [key, value] of Object.entries(person)) {
console.log(key, value); // name John, age 30
}Practical Patterns
Pattern 1: Array Processing
// Filter array
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let evens = [];
for (let num of numbers) {
if (num % 2 === 0) {
evens.push(num);
}
}
console.log(evens); // [2, 4, 6, 8, 10]
// Transform array
let prices = [10, 20, 30, 40];
let withTax = [];
for (let price of prices) {
withTax.push(price * 1.08);
}
console.log(withTax); // [10.8, 21.6, 32.4, 43.2]
// Find in array
let users = ["alice", "bob", "charlie"];
let searchName = "bob";
let found = false;
for (let user of users) {
if (user === searchName) {
found = true;
break;
}
}
console.log("Found:", found); // truePattern 2: Object Processing
// Count object properties
let settings = {
theme: "dark",
fontSize: 16,
autoSave: true,
language: "en"
};
let count = 0;
for (let key in settings) {
count++;
}
console.log("Settings count:", count); // 4
// Create new object with transformed values
let scores = { math: 85, english: 92, science: 78 };
let scaled = {};
for (let subject in scores) {
scaled[subject] = scores[subject] / 10;
}
console.log(scaled); // { math: 8.5, english: 9.2, science: 7.8 }
// Filter object properties
let user = {
name: "John",
age: 30,
password: "secret",
email: "john@test.com"
};
let publicInfo = {};
for (let key in user) {
if (key !== "password") {
publicInfo[key] = user[key];
}
}
console.log(publicInfo); // { name: "John", age: 30, email: "john@test.com" }Pattern 3: String Processing
// Count characters
let text = "hello world";
let charCount = {};
for (let char of text) {
if (char !== ' ') { // Ignore spaces
charCount[char] = (charCount[char] || 0) + 1;
}
}
console.log(charCount); // { h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1 }
// Check if palindrome
function isPalindrome(str) {
str = str.toLowerCase().replace(/[^a-z]/g, '');
let reversed = '';
for (let char of str) {
reversed = char + reversed;
}
return str === reversed;
}
console.log(isPalindrome("racecar")); // true
console.log(isPalindrome("hello")); // false
// Build acronym
let phrase = "Hypertext Markup Language";
let acronym = "";
for (let word of phrase.split(" ")) {
acronym += word[0];
}
console.log(acronym); // "HML"Practical Examples
Example 1: Shopping Cart Calculator
function calculateCartTotal(items) {
let subtotal = 0;
let itemCount = 0;
// Calculate subtotal using for...of
for (let item of items) {
subtotal += item.price * item.quantity;
itemCount += item.quantity;
}
// Apply discount based on total
let discount = subtotal >= 100 ? 0.1 : 0;
let discountAmount = subtotal * discount;
// Add tax
let taxRate = 0.08;
let tax = (subtotal - discountAmount) * taxRate;
// Calculate shipping
let shipping = subtotal >= 50 ? 0 : 5.99;
let total = subtotal - discountAmount + tax + shipping;
return {
items: itemCount,
subtotal: subtotal.toFixed(2),
discount: discountAmount.toFixed(2),
tax: tax.toFixed(2),
shipping: shipping.toFixed(2),
total: total.toFixed(2)
};
}
let cart = [
{ name: "Shirt", price: 29.99, quantity: 2 },
{ name: "Pants", price: 49.99, quantity: 1 },
{ name: "Socks", price: 9.99, quantity: 3 }
];
console.log(calculateCartTotal(cart));
// {
// items: 6,
// subtotal: "139.94",
// discount: "13.99",
// tax: "10.08",
// shipping: "0.00",
// total: "136.03"
// }Example 2: Object Validator
function validateUser(user, requiredFields) {
let errors = [];
// Check for required fields
for (let field of requiredFields) {
if (!user[field]) {
errors.push(`Missing required field: ${field}`);
}
}
// Validate specific fields
if (user.email && !user.email.includes("@")) {
errors.push("Invalid email format");
}
if (user.age && (user.age < 0 || user.age > 120)) {
errors.push("Age must be between 0 and 120");
}
if (user.password && user.password.length < 8) {
errors.push("Password must be at least 8 characters");
}
return {
valid: errors.length === 0,
errors: errors
};
}
let user1 = {
username: "john_doe",
email: "john@example.com",
age: 25,
password: "secret123"
};
let user2 = {
username: "jane",
email: "invalid-email",
age: 150
};
console.log(validateUser(user1, ["username", "email", "password"]));
// { valid: true, errors: [] }
console.log(validateUser(user2, ["username", "email", "password"]));
// {
// valid: false,
// errors: [
// "Missing required field: password",
// "Invalid email format",
// "Age must be between 0 and 120"
// ]
// }For...of and For...in Practice
Experiment with modern JavaScript loops
console.log() to see your output in the console above.Key Takeaways
for...ofiterates over VALUES (arrays, strings, sets, maps)for...initerates over KEYS/properties (objects)- Use
for...offor arrays, NOTfor...in for...ofworks with strings to iterate characters- Use
array.entries()to get index and value together - Modern approach:
Object.entries()withfor...offor objects for...ofis cleaner than traditional for loops for valuesfor...inreturns keys as strings- Both loops support
breakandcontinue - Choose the right loop for your data structure
What's Next?
You now understand how to use modern JavaScript loops for cleaner iteration! for...of and for...in make your code more readable and expressive.
In the next lesson, we'll learn about Break and Continue Statements—powerful tools for controlling loop execution. You'll learn how to exit loops early, skip iterations, and handle complex loop logic efficiently!
💪 Practice Challenge:
Before moving on, try creating:
- A function that uses
for...ofto find the longest word in an array - A function that uses
for...into count properties in an object - A character frequency counter using
for...ofon a string - A function that merges two objects using
for...in - An array reverser using
for...of(without reverse() method)