- Don't use
for-in
unless you use it with safeguards or are at least aware of why it might bite you. - Your best bets are usually
JavaScript has powerful semantics for looping through arrays and array-like objects. I've split the answer into two parts: Options for genuine arrays, and options for things that are just array-like, such as the
arguments
object, other iterable objects (ES2015+), DOM collections, and so on.For Actual Arrays
You have three options in ECMAScript 5 ("ES5"), the version most broadly supported at the moment, and will soon have two more in ECMAScript 2015 ("ES2015", "ES6"), the latest version of JavaScript that vendors are working on supporting:- Use
forEach
and related (ES5+) - Use a simple
for
loop - Use
for-in
correctly - Use
for-of
(use an iterator implicitly) (ES2015+) - Use an iterator explicitly (ES2015+)
1. Use forEach
and related
If you're using an environment that supports the Array
features of ES5 (directly or using a shim), you can use the new forEach
(spec
| MDN
): var a = ["a", "b", "c"];
a.forEach(function(entry) {
console.log(entry);
});
forEach
accepts an iterator function and, optionally, a value to use as this
when calling that iterator function (not used above). The iterator
function is called for each entry in the array, in order, skipping
non-existent entries in sparse arrays. Although I only used one argument
above, the iterator function is called with three: The value of each
entry, the index of that entry, and a reference to the array you're
iterating over (in case your function doesn't already have it handy).Unless you're supporting obsolete browsers like IE8 (which NetApps shows at just over 4% market share as of this writing in September 2016), you can happily use
forEach
in a general-purpose web page without a shim. If you do need to support obsolete browsers, shimming/polyfilling forEach
is easily done (search for "es5 shim" for several options).forEach
has the benefit that you don't have to declare
indexing and value variables in the containing scope, as they're
supplied as arguments to the iteration function, and so nicely scoped to
just that iteration.Additionally,
forEach
is the "loop through them all"
function, but ES5 defined several other useful "work your way through
the array and do things" functions, including:every
(stops looping the first time the iterator returnsfalse
or something falsey)some
(stops looping the first time the iterator returnstrue
or something truthy)filter
(creates a new array including elements where the filter function returnstrue
and omitting the ones where it returnsfalse
)map
(creates a new array from the values returned by the iterator function)reduce
(builds up a value by repeated calling the iterator, passing in previous values; see the spec for the details; useful for summing the contents of an array and many other things)reduceRight
(likereduce
, but works in descending rather than ascending order)
2. Use a simple for
loop
Sometimes the old ways are the best: var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
console.log(a[index]);
}
If the length of the array won't change during the loop, and it's in
performance-sensitive code (unlikely), a slightly more complicated
version grabbing the length up front might be a tiny bit faster:
var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
console.log(a[index]);
}
And/or counting backward:
var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
console.log(a[index]);
}
3. Use for-in
correctly
You'll get people telling you to use for-in
, but that's not what for-in
is for. for-in
loops through the enumerable properties of an object, not the indexes of an array. The order is not guaranteed, not even in ES2015 (ES6). ES2015 does define an order to object properties (via [[OwnPropertyKeys]]
, [[Enumerate]]
, and things that use them like Object.getOwnPropertyKeys
), but it does not define that for-in
will follow that order Still, it can be useful, particularly for sparse arrays, if you use appropriate safeguards:
// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
if (a.hasOwnProperty(key) && // These are explained
/^0$|^[1-9]\d*$/.test(key) && // and then hidden
key <= 4294967294 // away below
) {
console.log(a[key]);
}
}
Or if you're interested in just a "good enough for most cases" test, you could use this, but while it's close, it's not quite correct:
for (key in a) {
// "Good enough" for most cases
if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
console.log(a[key]);
}
}
4. Use for-of
(use an iterator implicitly) (ES2015+)
ES2015 adds iterators to JavaScript. The easiest way to use iterators is the new for-of
statement. It looks like this: var val;
var a = ["a", "b", "c"];
for (val of a) {
console.log(val);
}
Output:
a
b
c
5. Use an iterator explicitly (ES2015+)
Sometimes, you might want to use an iterator explicitly. You can do that, too, although it's a lot clunkier thanfor-of
. It looks like this: var a = ["a", "b", "c"];
var it = a.values();
var entry;
while (!(entry = it.next()).done) {
console.log(entry.value);
}
Full Source : Stackoverflow
Comments
Post a Comment