The for…of loop is a JavaScript statement that executes a block of code for each element of an iterable object, such as an array, a string, a map, a set, or a generator. For example, you can use a for…of loop to iterate over the elements of an array like this:
const fruits = ['apple', 'banana', 'cherry'];
for (const fruit of fruits) {
console.log(fruit);
}
// apple
// banana
// cherry
The for…of loop is different from the for…in loop, which iterates over the property names (or keys) of an object, not the values. It is also different from the Array.prototype.forEach() method, which executes a callback function for each element in the array.
const person = {name: "Alice", age: 25, occupation: "programmer"};
for (let prop in person) {
console.log(prop + ": " + person[prop]);
}
// name: Alice
// age: 25
// occupation: programmer
const numbers = [1, 2, 3];
numbers.forEach(function(number) {
console.log(number * 2);
});
// 2
// 4
// 6
Some advantages of using the for…of statement are:
However, the for…of loop does not provide the index of the element by default. If you need the index, you can use one of the following methods:
const fruits = ['apple', 'banana', 'cherry'];
for (const [index, fruit] of fruits.entries()) {
console.log(`index: ${index}, fruit: ${fruit}`);
}
// index: 0, fruit: apple
// index: 1, fruit: banana
// index: 2, fruit: cherry
const fruits = ['apple', 'banana', 'cherry'];
for (const fruit of fruits) {
const index = fruits.indexOf(fruit);
console.log(`index: ${index}, fruit: ${fruit}`);
}
// index: 0, fruit: apple
// index: 1, fruit: banana
// index: 2, fruit: cherry
Note that this method is less efficient than the previous one, as it requires searching the array on each iteration. If the array contains duplicate elements then it won’t work as you expected:
const fruits = ['apple', 'banana', 'banana', 'cherry'];
for (const fruit of fruits) {
const index = fruits.indexOf(fruit);
console.log(`index: ${index}, fruit: ${fruit}`);
}
// index: 0, fruit: apple
// index: 1, fruit: banana
// index: 1, fruit: banana
// index: 3, fruit: cherry
const fruits = ['apple', 'banana', 'cherry'];
let index = 0;
for (const fruit of fruits) {
console.log(`index: ${index}, fruit: ${fruit}`);
index++;
}
// index: 0, fruit: apple
// index: 1, fruit: banana
// index: 2, fruit: cherry
An iterable object in JavaScript is an object that can be iterated over with the for…of statement. It means that the object has a special method called Symbol.iterator that returns an iterator object.
An iterator object is an object that has a next() method that returns an object with two properties: value and done. The value property holds the current value of the iteration, and the done property is a boolean that indicates whether the iteration is finished or not.
Some built-in objects in JavaScript are iterable by default, such as arrays, strings, maps, sets, and generators. For example:
const array = [1, 2, 3];
const string = "hello";
const map = new Map([["a", 1], ["b", 2]]);
const set = new Set([1, 2, 3]);
function* generator() {
yield 1;
yield 2;
yield 3;
}
// These objects are all iterable
for (let x of array) console.log(x); // 1, 2, 3
for (let x of string) console.log(x); // h, e, l, l, o
for (let x of map) console.log(x); // ["a", 1], ["b", 2]
for (let x of set) console.log(x); // 1, 2, 3
for (let x of generator()) console.log(x); // 1, 2, 3
However, some objects are not iterable by default, such as plain objects or numbers. For example:
const object = {name: "Alice", age: 25};
const number = 42;
// These objects are not iterable
for (let x of object) console.log(x); // TypeError: object is not iterable
for (let x of number) console.log(x); // TypeError: number is not iterable
To make an object iterable, we need to define the Symbol.iterator method on it and return an iterator object from it. For example:
const range = {
from: 1,
to: 5,
};
// Define the Symbol.iterator method
range[Symbol.iterator] = function () {
// Return the iterator object
return {
current: this.from,
last: this.to,
// Define the next() method
next() {
// Return the value and done properties
if (this.current <= this.last) {
return { value: this.current++, done: false };
} else {
return { done: true };
}
},
};
};
// Now range is iterable
for (let x of range) console.log(x); // 1, 2, 3, 4, 5
The for…in statement in JavaScript is used to loop over the property keys of an object. It is not recommended to use it on arrays, because it has some pitfalls, such as:
For example:
const array = [1, 2, 3];
array.foo = "bar"; // add a non-index property
Array.prototype.baz = "qux"; // add a prototype property
for (let x in array) {
console.log(x); // 0, 1, 2, foo, baz
console.log(x + 1); // 01, 11, 21, foo1, baz1
}
As you can see, the for…in loop iterates over the non-index properties and the prototype property, and also returns the index as a string. This may not be what you want when looping over an array.