Loop through an array in JavaScript
Solution 1
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
andcontinue
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:
Solution 2
Yes, assuming your implementation includes the for
...of
feature introduced in ECMAScript 2015 (the "Harmony" release)... which is a pretty safe assumption these days.
It works like this:
// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
// ... do something with s ...
}
Or better yet, since ECMAScript 2015 also provides block-scoped variables:
// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
// ... do something with s ...
}
// s is no longer defined here
(The variable s
is different on each iteration, but can still be declared const
inside the loop body as long as it isn't modified there.)
A note on sparse arrays: an array in JavaScript may not actually store as many items as reported by its length
; that reported number is simply one greater than the highest index at which a value is stored. If the array holds fewer elements than indicated by its length, its said to be sparse. For example, it's perfectly legitimate to have an array with items only at indexes 3, 12, and 247; the length
of such an array is reported as 248, though it is only actually storing 3 values. If you try to access an item at any other index, the array will appear to have the undefined
value there. So when you want to "loop through" an array, you have a question to answer: do you want to loop over the full range indicated by its length and process undefined
s for any missing elements, or do you only want to process the elements actually present? There are plenty of applications for both approaches; it just depends on what you're using the array for.
If you iterate over an array with for
..of
, the body of the loop is executed length
times, and the loop control variable is set to undefined
for any items not actually present in the array. Depending on the details of your "do something with" code, that behavior may be what you want, but if not, you should use a different approach.
Of course, some developers have no choice but to use a different approach anyway, because for whatever reason they're targeting a version of JavaScript that doesn't yet support for
...of
.
As long as your JavaScript implementation is compliant with the previous edition of the ECMAScript specification (which rules out, for example, versions of Internet Explorer before 9), then you can use the Array#forEach
iterator method instead of a loop. In that case, you pass a function to be called on each item in the array:
var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) {
// ... do something with s ...
} );
Unlike for
...of
, .forEach
only calls the function for elements that are actually present in the array. If passed our hypothetical array with three elements and a length of 248, it will only call the function three times, not 248 times. It also distinguishes between missing elements and elements that are actually set to undefined
; for the latter, it will still call the function, passing undefined
as the argument. If this is how you want to handle sparse arrays, .forEach
may be the way to go even if your interpreter supports for
...of
.
The final option, which works in all versions of JavaScript, is an explicit counting loop. You simply count from 0 up to one less than the length and use the counter as an index. The basic loop looks like this:
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
s = myStringArray[i];
// ... do something with s ...
}
One advantage of this approach is that you can choose how to handle sparse arrays; the above code will run the body of the loop the full length
times, with s
set to undefined
for any missing elements, just like for
..of
. If you instead want to handle only the actually-present elements of a sparse array, like .forEach
, you can add a simple in
test on the index:
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
if (i in myStringArray) {
s = myStringArray[i];
// ... do something with s ...
}
}
Assigning the length value to the local variable (as opposed to including the full myStringArray.length
expression in the loop condition) can make a significant difference in performance since it skips a property lookup each time through; using Rhino on my machine, the speedup is 43%.
You may see the length caching done in the loop initialization clause, like this:
var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {
The explicit counting loop also means you have access to the index of each value, should you want it. The index is also passed as an extra parameter to the function you pass to forEach
, so you can access it that way as well:
myStringArray.forEach( function(s, i) {
// ... do something with s and i ...
});
for
...of
doesn't give you the index associated with each object, but as long as the object you're iterating over is actually an Array
(for
..of
works for other iterable types which may not have this method), you can use the Array#entries method to change it to an array of [index, item] pairs, and then iterate over that:
for (const [i, s] of myStringArray.entries()) {
// ... do something with s and i ...
}
The for
...in
syntax mentioned by others is for looping over an object's properties; since an Array in JavaScript is just an object with numeric property names (and an automatically-updated length
property), you can theoretically loop over an Array with it. But the problem is that it doesn't restrict itself to the numeric property values (remember that even methods are actually just properties whose value is a closure), nor is it guaranteed to iterate over those in numeric order. Therefore, the for
...in
syntax should not be used for looping through Arrays.
Solution 3
You can use map
, which is a functional programming technique that's also available in other languages like Python and Haskell.
[1,2,3,4].map( function(item) {
alert(item);
})
The general syntax is:
array.map(func)
In general func
would take one parameter, which is an item of the array. But in the case of JavaScript, it can take a second parameter which is the item's index, and a third parameter which is the array itself.
The return value of array.map
is another array, so you can use it like this:
var x = [1,2,3,4].map( function(item) {return item * 10;});
And now x is [10,20,30,40]
.
You don't have to write the function inline. It could be a separate function.
var item_processor = function(item) {
// Do something complicated to an item
}
new_list = my_list.map(item_processor);
which would be sort-of equivalent to:
for (item in my_list) {item_processor(item);}
Except you don't get the new_list
.
Solution 4
for (const s of myStringArray) {
(Directly answering your question: now you can!)
Most other answers are right, but they do not mention (as of this writing) that ECMAScript 6 2015 is bringing a new mechanism for doing iteration, the for..of
loop.
This new syntax is the most elegant way to iterate an array in JavaScript (as long you don't need the iteration index).
It currently works with Firefox 13+, Chrome 37+ and it does not natively work with other browsers (see browser compatibility below). Luckily we have JavaScript compilers (such as Babel) that allow us to use next-generation features today.
It also works on Node.js (I tested it on version 0.12.0).
Iterating an array
// You could also use "let" or "const" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) {
console.log(letter);
}
Iterating an array of objects
const band = [
{firstName : 'John', lastName: 'Lennon'},
{firstName : 'Paul', lastName: 'McCartney'}
];
for(const member of band){
console.log(member.firstName + ' ' + member.lastName);
}
Iterating a generator:
(example extracted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)
function* fibonacci() { // A generator function
let [prev, curr] = [1, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (const n of fibonacci()) {
console.log(n);
// Truncate the sequence at 1000
if (n >= 1000) {
break;
}
}
Compatibility table: http://kangax.github.io/compat-table/es6/#test-for..of_loops
Specification: http://wiki.ecmascript.org/doku.php?id=harmony:iterators
}
Solution 5
In JavaScript it's not advisable to loop through an Array with a for-in loop, but it's better to use a for
loop such as:
for(var i=0, len=myArray.length; i < len; i++){}
It's optimized as well ("caching" the array length). If you'd like to learn more, read my post on the subject.
Mark Szymanski
Updated on July 08, 2022Comments
-
Mark Szymanski almost 2 years
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?
-
Mark Szymanski almost 14 yearsOk, so I'm a bit confused, it's ok to use the enhanced for loop when you are accessing the objects? And use a sequential one for filling one? Is this correct?
-
Christian C. Salvadó almost 14 yearsno, it's really simple, array objects have numeric indexes, so you want to iterate over those indexes in the numeric order, a sequential loop ensures that, the enhanced
for-in
loop enumerates object properties, without an specific order, and it also enumerates inherited properties... for iterating over arrays sequential loops are always recommended... -
jondavidjohn over 12 yearsrelated - stackoverflow.com/questions/5349425/…
-
user3167101 over 8 yearsrelated - stackoverflow.com/q/6208964/31671
-
Hamed Mahmoudkhani over 7 yearsAlso :
myStringArray.forEach(function(value, index){ console.log(index, value) });
and result will be0 "Hello" 1 "World"
-
EscapeNetscape over 7 yearsjsben.ch/#/Q9oD5 <= Here a benchmark of a bunch of solutions for looping through arrays
-
Roobie Nuby over 5 years@EscapeNetscape the link has changed and is now jsben.ch/Q9oD5. To summarize, sequential for loop takes 60% of the time that for-in takes.
-
jpmc26 over 5 years@CMS No, it's not really simple. It's really simple in every other language. It's ridiculously complex in JS, where you have
in
andof
that can both be used and do different things. Then you also haveforEach
and the ugly and annoying index based looping. Every other modern language makes looping over a collection easy and straightforward with no surprises or confusion. JS could, too, but it doesn't. -
cobrexus over 3 yearsDoes this answer your question? For-each over an array in JavaScript
-
Voxlinou over 2 yearsWhy isn't this question answered, people have put gigantic enermy into putting a correct, formal, with pros and cons and no answer is confirmed? I don't see a single error on their answers. Please set an anwer as confirmed
-
-
harto almost 14 yearsThat particular example is probably better implemented using
Array.forEach
.map
is for generating a new array. -
Christian C. Salvadó almost 14 years@hasen, the
Array.prototype.map
method is part of the ECMAScript 5th Edition Standard, is not yet available on all implementations (e.g. IE lacks of it), also for iterating over an array I think theArray.prototype.forEach
method is more semantically correct... also please don't suggest the for-in statement, see my answer for more details :) -
Chris Cooper about 12 yearsThe first example of the "while" syntax won't work if any of the array elements is falsy.
-
Kzqai about 12 yearsIt seems that this would run up against similar problems as other for in usages with an array object, in that prototype member variables would be caught by the for in as well.
-
Phrogz almost 12 yearsNote that some interpreters (e.g. V8) will automatically cache the length of the array if the code is called enough times and it detects that the length is not modified by the loop.
-
Phrogz almost 12 yearsNote that some interpreters (e.g. V8) will automatically cache the length of the array if the code is called enough times and it detects that the length is not modified by the loop. While caching the length is still nice, it may not provide a speed boost when your code is being invoked enough times to actually make a difference.
-
Gabriel almost 12 yearsThanks for the info @Phrogz it's true that there is a lot of optimizations that the VM can make, but since older browsers don't have this it would still be best practice to optimize for it since it is so cheap.
-
Christian C. Salvadó about 11 yearsNotice that with this approach the loop will stop as soon it finds a falsey value, such as an empty string,
0
,false
,NaN
,null
orundefined
, even beforei
reaches the length, e.g.: jsfiddle.net/prvzk/1 -
Stijn de Witt about 11 yearsFor the people that don't get what is so ingenious: The i-- expression is first evaluated and allows the loop to continue when it's not falsish... Afterwards the counter is decremented. As soon as i becomes zero it will break out of the loop as zero is a falsish value in Javascript.
-
Stijn de Witt about 11 yearsAgreed with Exception. Do not underestimate the impact of extra dependencies. I would advice against this except in code that is already heavily using jQuery anyway.
-
Stijn de Witt about 11 years@Gabriel: Why? Please give real-world examples showing that not caching the length is actually a performance bottleneck. I follow the 'premature optimization is the root of all evil' approach. I will fix that one loop that actually poses a problem once I encounter it...
-
Stijn de Witt about 11 years... and this while loop is equivalent to: for (var i=0,item; item=items[i]; i++) , which takes away the need to declare the index and item variables beforehand...
-
Gabriel about 11 years@StijndeWitt imo it is just a stylistic issue. Honestly I no longer even use for loops instead relying on underscore for things like _.each, _.map etc. to do these things. When I did write loops like this I cached the length primarily so that all my variable declaration were in one place, at the top of my function. Following my advice in this regard is inconsequential to any real world application. Premature optimization is super bad, but if optimization happens to result from stylistic decisions I don't think it actually matters.
-
danwellman about 11 yearsfalsish? You mean falsey. Let's all stick the proper terminology to avoid confusion ;)
-
Mark Reed over 10 yearsFor new discoverers of this question, I'd just like to point out Lo-Dash, a spiritual successor of Underscore's that improves upon it in many ways.
-
daniel1426 about 10 yearsThe loop condition could be
(item=someArray[i]) !== undefined
. -
Deniz Ozger about 10 yearsThis loop doesn't seem to follow order of items in the array.
-
molokoloco about 10 yearsMy test was wrong. It's correct, showing all LOOPS now. jsperf.com/native-loop-performance/16
-
Matt almost 10 yearsfor/in loops are discouraged for array enumeration, as the order of eumeration is not guaranteed, and it enumerates properties, not just array elements. For more info, see stackoverflow.com/questions/500504/…, or even the accepted answer of this question; stackoverflow.com/a/3010848/444991
-
Sambhav Sharma almost 10 yearswell, thanks for the update.. and what about the situation when we don't care about the order of the array? Will this still be discouraged?
-
Matt almost 10 yearsIt'll still be discouraged because it enumerates all the properties, not just the array elements. The two posts I linked to explain this in more detail.
-
Stijn de Witt almost 10 years@bergi is right. This loop wipes out the array as it loops through it. Not what you want in most cases.
-
njzk2 almost 10 yearsbreaks on falsey items.
-
Noz almost 10 years@Gabriel I believe JavaScript already supports the map function on arrays, no need to introduce an additional lib for that.
-
Daniel Sokolowski over 9 yearsAnd how about using
for (var i in array) if (++i)
? -
Walter Chapilliquen - wZVanG almost 9 years
-
user513951 over 8 yearsThis exact functionality is already part of Mark Reed's answer.
-
Stijn de Witt over 8 years@Noz
map
has only since recently enjoyed broad browser support... And of course underscore offers more than just that. But I wholeheartedly agree that if possible and not unreasonably more complex, using vanilla JS over a library is always the better option. Dependencies are bad. Try to avoid them. -
brk over 7 years
for...in
should be avoided for Array-like objects -
Stijn de Witt almost 7 yearsUpdate: These days, you can use Array.forEach to get much of the same effect with native arrays.
-
Michel Jung over 6 yearsYou'd rather want to use
.forEach()
and drop thereturn e;
-
marpme over 6 yearsas
map
implies, the functionmap
is for mapping a certain value to something else, hence I would not suggest using that one for this certain example. -
DarckBlezzer over 5 yearsis better use
i = i +1
instead ofi++
-
domdambrogia about 5 yearsWas it really necessary to bring jQuery or HTML into this?
-
PowerStat almost 5 yearsCould be improved: Please use: ++i instead of i++, this will avoid an temporary object. So it reduces memory usage and cpu time (no allocation required)!
-
colxi almost 5 years@PowerStat can you provide a link or reference about that ? I've never aheard about it, sounds interesting...
-
PowerStat almost 5 years@colxi For such interesting things you should read the hardcore C++ stuff from Herb Sutter and Scott Meyers. The ++i vs i++ thing is from the book: Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions - I thing you could also find it on gotw.ca but can be proved for every programing language.
-
Sapphire_Brick over 4 yearsWhy is it better? of course, you can do that in java as well, bu he asked about a foreach loop.
-
Sapphire_Brick over 4 yearsthat's the Haskell-y way to do it; keep taking the first one. clever, but probably slow.
-
Sapphire_Brick about 4 yearsThat's not very clean compared to
z.forEach(j => console.log(j));
. -
Kamil Kiełczewski almost 4 years@Sapphire_Brick actually it is quite fast - here is test
-
Sapphire_Brick almost 4 yearsOf course a simple program like this is fast, but how does it scale in comparison to
for(...;...;...)
orfor(... of ...)
? -
Kamil Kiełczewski almost 4 years@Sapphire_Brick don't be lazy! :) you can check it your self- I give you link (test) to tool in above comment. However for small array case (as OP uses) when you need to optimize speed you should choose solution fastest for small arrays (not for big arrays - which can be different)
-
Sapphire_Brick almost 4 yearsYou have make a good point. I ran your example with an array of 1000 items, and
while(a.length) { console.log(a.shift()); }
was about twice as fast as thefor(var i = 0; i < a.length; i++) { console.log(a[i]); }
version. ¯\_(ツ)_/¯ -
Kamil Kiełczewski almost 4 years@Sapphire_Brick - thank you for your comment - I tink using console.log in tests is not good because it is complex system function and have big impact on run time. I check with
r+=a[i].length
(sum of words length) for array witch 1000 elements - and still this solution was much faster than other solution (and probaly the speed difference grow when number of elements grow...) - I'm surprised too that this solution is so fast :) -
John Lord over 3 yearsyour "some code" should have had an example in it. It isn't entirely clear if the variables are passed in directly or as "this" or whatever.
-
Peter Mortensen over 3 years@domdambrogia: It is a meme.
-
Peter Mortensen over 3 yearsEven if it does not exist in your native language, you should not leave out articles in English (the indefinite article ("a" or "an") and the definite article ("the")). See e.g. English Articles - 3 Simple Rules To Fix Common Grammar Mistakes & Errors and A, AN, THE - Articles in English.
-
Arthur S over 3 yearsThis isn't esoteric. Its simply unnecessary and makes an assumption that the
a
variable will not be used in further code. -
Pitouli about 3 yearsCareful! The benchmark is wrong, because the array is not reset between each execution. Since the shift() has emptied the array after the first execution, all the subsequent executions are indeed extremely fast :p When you correctly reset the array, it appears that this solution is the second slowest. jsbench.me/4dklq1kjef/1
-
Kamil Kiełczewski about 3 years@Pitouli you are right - I rollback answer to its initial form. When I have more time then I will perform benchamarks again
-
bmaupin almost 3 yearsI know this answer predates async and Promises, but I feel this is worth mentioning in any conversation pertaining to modern JavaScript: "
forEach
does not wait for promises. Make sure you are aware of the implications while using promises (or async functions) asforEach
callback." (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…) -
Aleksandr Golovatyi almost 3 years"for" and "for in" loops create extra variable, "forEach" - create extra function context. I think the best way is "for of".
-
YesItsMe almost 3 yearsdo you care to elaborate why 4 "for of" is the best over the others
-
Aleksandr Golovatyi almost 3 yearsIt doesn't create needless variables or function context. But if you don't care about small disadvantages you can use any of them, what is more comfortable for you. @YesItsMe Thank you for the question.
-
Vic over 2 yearscon of es6
for-of
: can't get the current index -
Alvaro Carvalho about 2 years@Vic you can, but it's not straightforward.
-
S. W. G. about 2 yearsWhat about the
for(let ojb of objs)
statement? -
Scotty Jamison almost 2 yearsFor reference, this is how to get the current index as you loop. I personally find this pretty straightforwards.
for (const [i, x] of yourArray.entries()) { ... }
. -
Scotty Jamison almost 2 yearsFor those looking at this answer and wondering whether they should choose forEach() of for-of, I would just recommend using for-of. for-of is the newer looping syntax that entirely replaces the need for forEach. There isn't anything that for-of offers that forEach does not, but the inverse isn't true.
-
Adam almost 2 yearsI think the mentioned contra of missing "continue" is not really true, just use return inside the functions, its the equivalent. However, the missing "break" is a valid contra point.