====== 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.