JavaScript Loop Constructs: A Comprehensive Comparison
1. Traditional Array Iteration Methods
Basic for Loop
const data = [10, 20, 30, 40, 50, 60, 70];
for (let i = 0; i < data.length; i++) {
console.log(i, data[i]);
}
Optimized for Loop
Cache the array length to improve performance, especially with large arrays:
for (let j = 0, size = data.length; j < size; j++) {
console.log(data[j]);
}
2. forEach Method
The forEach method provides elements directly and works only with arrays. It cannot be interrupted with break or return statements to exit the outer function.
const values = [1, 2, 3, 4, 5, 6, 7];
values.forEach(item => {
console.log(item);
});
values.forEach(function(item) {
console.log(item);
});
3.1. Using for-in with Arrays
The for-in loop retrieves array indices (as strings):
const numbers = [1, 2, 3, 4, 5, 6, 7];
for (let index in numbers) {
console.log(index, numbers[index]);
}
3.2. Using for-in with Objects
The for-in loop works with enumerable objects, returning property names:
const config = {
optionA: true,
optionB: 100,
optionC: "example"
};
for (let key in config) {
console.log(key, config[key]);
}
Important considerations when using for-in:
- Indices are string values, not numbers, so mathematical operations require conversion
- Traversal order may not match the actual array's internal order
- for-in enumerates all enumerable properties, including those from the prototype chain
Due to these limitations, for-in is better suited for object properties rather than array elements. For array iteration, ES6's for-of offers a more reliable solution.
4. ES6 for-of Loop
The for-of loop provides elements directly and works with arrays, strings, Maps, Sets, and other iterable objects:
const items = [1, 2, 3, 4, 5, 6, 7];
for (const element of items) {
console.log(element);
}
const text = "helloabc";
for (const char of text) {
console.log(char);
}
Key Differences
- for-in iterates over property names (keys/indexes), while for-of iterates over property values
- for-of works with arrays, array-like objects, strings, Maps, Sets, and other iterable collections
- Unlike forEach(), for-of properly responds to break, continue, and return statements
Special Cases
Iterating Over Object Properties
Since for-of doesn't work directly with plain objects, use for-in or Object.keys():
for (const key of Object.keys(someObject)) {
console.log(key + ": " + someObject[key]);
}
Iterating Over Maps
Destructuring is particularyl useful when iterating over Maps:
for (const [name, phone] of phoneBookMap) {
console.log(name + "'s phone number is: " + phone);
}
Creating Custom Iterables
By adding a Symbol.iterator method to an object, you can make it iterable:
jQuery.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Objects with Symbol.iterator are called iterable. This concept is fundamental throughout JavaScript, affecting not just for-of loops but also Map and Set constructors, destructuring assignments, and the spread operator.
How for-of Works
The for-of loop first calls the collection's Symbol.iterator method, which returns a new iterator object. This object must have a next() method that for-of will repeatedly call. Here's a simple iterator example:
const zeroIterator = {
[Symbol.iterator]: function () {
return this;
},
next: function () {
return {done: false, value: 0};
}
};
Performance Comparison
From fastest to slowest: traditional for > for-of > forEach > for-in