Loop through an array in JavaScript
arrays, for-loop, javascript, loops
Solution
Three main options:
- `for (var i = 0; i < xs.length; i++) { console.log(xs[i]); }`
- `xs.forEach((x, i) => console.log(x));`
- `for (const x of xs) { console.log(x); }`
Detailed examples are below.
1. Sequential `for` loop:
var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
console.log(myStringArray[i]);
//Do something
}
Pros
- Works on every environment
- You can use `break` and `continue` flow control statements
Cons
- Too verbose
- Imperative
- Easy to have off-by-one errors (sometimes also called a fence post error)
2. `Array.prototype.forEach`:
The ES5 specification introduced a lot of beneficial array methods. One of them, the `Array.prototype.forEach`, gave us a concise way to iterate over an array:
const array = ["one", "two", "three"]
array.forEach(function (item, index) {
console.log(item, index);
});
Being almost ten years as the time of writing that the ES5 specification was released (Dec. 2009), it has been implemented by nearly all modern engines in the desktop, server, and mobile environments, so it's safe to use them.
And with the ES6 arrow function syntax, it's even more succinct:
array.forEach(item => console.log(item));
Arrow functions are also widely implemented unless you plan to support ancient platforms (e.g., Internet Explorer 11); you are also safe to go.
Pros
- Very short and succinct.
- Declarative
Cons
- Cannot use `break` / `continue`
Normally, you can replace the need to `break` out of imperative loops by filtering the array elements before iterating them, for example:
array.filter(item => item.condition < 10)
.forEach(item => console.log(item))
Keep in mind if you are iterating an array to build another array from it, you should use `map`. I've seen this anti-pattern so many times.
Anti-pattern:
const numbers = [1,2,3,4,5], doubled = [];
numbers.forEach((n, i) => { doubled[i] = n * 2 });
Proper use case of map:
const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);
console.log(doubled);
Also, if you are trying to reduce the array to a value, for example, you want to sum an array of numbers, you should use the reduce method.
Anti-pattern:
const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });
Proper use of reduce:
const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);
console.log(sum);
3. ES6 `for-of` statement:
The ES6 standard introduces the concept of iterable objects and defines a new construct for traversing data, the `for...of` statement.
This statement works for any kind of iterable object and also for generators (any object that has a `\[Symbol.iterator\]` property).
Array objects are by definition built-in iterables in ES6, so you can use this statement on them:
let colors = ['red', 'green', 'blue'];
for (const color of colors){
console.log(color);
}
Pros
- It can iterate over a large variety of objects.
- Can use normal flow control statements (`break` / `continue`).
- Useful to iterate serially asynchronous values.
Cons
- If you are targeting older browsers, the transpiled output might surprise you.
Do not use `for...in`
@zipcodeman suggests the use of the `for...in` statement, but for iterating arrays `for-in` should be avoided, that statement is meant to enumerate object properties.
It shouldn't be used for array-like objects because:
- The order of iteration is not guaranteed; the array indexes may not be visited in numeric order.
- Inherited properties are also enumerated.
The second point is that it can give you a lot of problems, for example, if you extend the `Array.prototype` object to include a method there, that property will also be enumerated.
For example:
Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];
for (var i in array) {
console.log(array[i]);
}
The above code will console log "a", "b", "c", and "foo!".
That can be particularly a problem if you use some library that relies heavily on native prototypes augmentation (such as MooTools).
The `for-in` statement, as I said before, is there to enumerate object properties, for example:
var obj = {
"a": 1,
"b": 2,
"c": 3
};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
console.log("prop: " + prop + " value: " + obj[prop])
}
}
In the above example, the `hasOwnProperty` method allows you to enumerate only own properties. That's it, only the properties that the object physically has, no inherited properties.
I would recommend you to read the following article:
- Enumeration VS Iteration
Problem
In Java, you can use a `for` loop to traverse objects in an array as follows: ``` String[] myStringArray = {"Hello", "World"}; for (String s : myStringArray) { // Do something } ``` Can I do the same in JavaScript?
Related problems
- Loop (for each) over an array in JavaScript
- Why is using "for...in" for array iteration a bad idea?
- What's the fastest way to loop through an array in JavaScript?
- Is reading the `length` property of an array really that expensive an operation in JavaScript?
- post increment vs pre increment - Javascript Optimization
- Strange behavior in Javascript enhanced for...in loop
- How to loop through array in jQuery?
- "Object is possibly 'undefined'." in TypeScript