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.