====== For In vs For Of ======
The **for...in** and **for...of** loops are used to iterate over the properties of objects or elements of an iterable, but they do it in different ways.
===== For In =====
The **for...in** loop iterates over all enumerable properties of an object, including inherited ones.
;;;It gives you the keys (property names) of the object.;;;
==== Example with an Object ====
const obj = {a: 1, b: 2, c: 3};
for (const key in obj) {
console.log(key, obj[key]); // Logs 'a 1', 'b 2', 'c 3'
}
==== Example with an Array ====
const arr = [10, 20, 30];
arr.foo = 'bar';
for (const key in arr) {
console.log(key, arr[key]); // Logs '0 10', '1 20', '2 30', 'foo bar'
}
Be cautious using **for...in** with arrays, as it will also include enumerable properties that are not indices. \\
Example:
const numbers = [4, 8, 15, 16, 23, 42];
numbers.foo = "I'm a property, not a number!";
for (const key in numbers) {
console.log(`key = ${key}, numbers[${key}] = ${numbers[key]}`);
}
// Output will be:
// key = 0, numbers[0] = 4
// key = 1, numbers[1] = 8
// key = 2, numbers[2] = 15
// key = 3, numbers[3] = 16
// key = 4, numbers[4] = 23
// key = 5, numbers[5] = 42
// key = foo, numbers[foo] = I'm a property, not a number!
for...in loop **also iterates over the foo property**, which is why this loop type must be used with caution when working with arrays.
===== For Of =====
The **for...of** loop ;;;iterates over the values;;; of an iterable object (such as an **array, set, or map**).
It gives you the values of the iterable directly. \\
It can't be used directly on plain objects without using methods like Object.keys, Object.values, or Object.entries.
==== Example with an Array ====
const arr = [10, 20, 30];
for (const value of arr) {
console.log(value); // Logs '10', '20', '30'
}
==== Example with an Object ====
The **for...of** loop is designed to work with iterable objects, such as arrays, strings, maps, sets, etc. Ordinary objects are not iterable by default, so **attempting to use for...of with an object will lead to an error.**
However, you can convert an object's keys, values, or key-value pairs into an array and then iterate over that array with a for...of loop. \\
Example:
const person = {
name: 'Alice',
age: 30,
profession: 'Engineer',
};
// Iterate over keys
for (const key of Object.keys(person)) {
console.log(`Key: ${key}`);
}
// Iterate over values
for (const value of Object.values(person)) {
console.log(`Value: ${value}`);
}
// Iterate over key-value pairs
for (const [key, value] of Object.entries(person)) {
console.log(`Key: ${key}, Value: ${value}`);
}
// Output:
// Key: name
// Key: age
// Key: profession
// Value: Alice
// Value: 30
// Value: Engineer
// Key: name, Value: Alice
// Key: age, Value: 30
// Key: profession, Value: Engineer
In this example, **Object.keys(person)**, **Object.values(person**), and **Object.entries(person)** return arrays of the object's keys, values, and key-value pairs, respectively, allowing you to iterate over them with a **for...of** loop.
===== Conclusion =====
* Use **for...in** to iterate over the **keys** of an **object** (including non-array objects).
* Use **for...of** to iterate over the **values** of iterables like **arrays, sets, and maps**.
* Be cautious using **for...in with arrays**, especially if you have added custom properties, as it can lead to unexpected results.