Written by 11:13 Basics of JavaScript, Languages & Coding

Iterating Over JavaScript Arrays

Iterating Over Arrays

The article describes ES5 and ES6 approaches to iterate over javascript arrays and array-like objects!

There are three ways to iterate through an array:

  1. The Array.prototype.forEach method;
  2. The for loop;
  3. The for..in statement.

Additionally, two new methods are expected with the introduction of the new ECMAScript 6 standard:

  1. The for…of statement;
  2. The explicit use of the iterator.

The forEach method

Example of use:

var a = ["a", "b", "c"];
a.forEach(function (entry) {
    console.log(entry);
});

Basically, in order to use the forEach method in browsers that do not have a native support for this method, you need to utilize the es5-shim library. These include IE 8 and earlier versions that are still in use. You do not need to declare local variables to store the index and the value of the current array element since they are automatically passed to the callback function as arguments. This is one of the main advantages of the forEach method.

In addition to the forEach method, ES5 provides other useful methods that can be used to iterate over elements:

  • every — invokes the provided callback function once for each element present in the array until it finds one where callback returns a false value.
  • some — checks whether an element in the array passes the test implemented by the provided function.
  • filter — creates a new array with all elements that pass the test implemented by the provided function.
  • map — creates a new array with the results of calling a provided function on every element in this array.
  • reduce — applies a function against an accumulator and each value of the array (from left-to-right) has to reduce it to a single value.
  • reduceRight — applies a function against an accumulator and each value of the array (from right-to-left) has to reduce it to a single value.

The for loop

Here is an example of the for loop

var a = ["a", "b", "c"];
var index;
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

or you can use it as follows

var a = ["a", "b", "c"];
var index, len;
for (index = 0, len = a.length; index < len; ++index) {
    console.log(a[index]);
}

In theory, this code must run a bit faster than the previous one.
We can go even further and get rid of the variable that stores the array length, by changing the order of the iteration (provided that the order of the iteration is not important):

var a = ["a", "b", "c"];
var index;
for (index = a.length - 1; index >= 0; --index) {
    console.log(a[index]);
}

However, in modern JavaScript engines, such optimizations games do not make any sense.

The for…in loop

Keep in mind that this method is not really intended for iterating over arrays. The for…in statement iterates through the enumerable properties of an object, in arbitrary order. At the same time, in some cases, like iterating over sparse arrays the for…in statement can be useful.

// a is a sparse array
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (var key in a) {
    if (a.hasOwnProperty(key) &&
        /^0$|^[1-9]\d*$/.test(key) &&
        key <= 4294967294) {
        console.log(a[key]);
    }
}

There are two checks on each iteration in this example:

    1. The array has the key property, which is not inherited from its prototype
    2. The key is a string that contains the decimal notation of an integer, the value of which is less than 4 294 967 294.

Where does this number come from ? It comes immediately from the definition of an array index in ES5, that states that the largest index, which an array element can have is (2^32 – 2) = 4 294 967 294.

Of course, these checks will take away the extra time, when performing the loop. But in the case of a sparse array, this method is more efficient than the for loop. This is because we only iterating over elements that are explicitly defined in the array. Thus, we will have only 3 iterations (for index 0, 10 and 10000) instead of 10001 in the for loop. You can create a separate function, to avoid this tedious code for checks, whenever you need to iterate over an array.

function arrayHasOwnIndex(array, key) {
    return array.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key)
                                              && key <= 4294967294;
}

Then the body of the loop (from the example above) will be reduced:

for (key in a) {
    if (arrayHasOwnIndex(a, key)) {
        console.log(a[key]);
    }
}

The above code for checks is versatile and is suitable for all occasions. However, you can use a shorter version. Although it is not quite correct, but nevertheless suitable for the majority of cases:

for (key in a) {
    if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) {
        console.log(a[key]);
    }
}

The for…of loop. Implicit use of the iterator

Currently, the ES6 specification has the DRAFT status, but it should introduce the JavaScript iterators.

In object-oriented computer programming, an iterator is an object that enables a programmer to traverse a container, particularly lists. An iterator is an object that defines the next() method. The next() method is a function without arguments that returns an object with two properties:

  1. done (boolean) — true if the iterator has reached the end of the sequence. Otherwise false.
  2. value — defines the value returned by the iterator. May be undefined or be absent, if the done property is true.

Embedded objects, including arrays, have default iterators. The simplest way to use the iterator within arrays is to use the new for…of statement.

The following code demonstrates the usage of the for…of loop.

var val;
var a = ["a", "b", "c"];
for (val of a) {
    console.log(val);
}

In this example, the for…of loop implicitly calls the Array’s iterator to retrieve each value in the array.

The explicit use of an iterator.

Iterators can also be used explicitly, however, in this case, the code becomes much more difficult compared to for…of usage. It looks like this:

var a = ["a", "b", "c"];
var it = a.entries();
var entry;
while (!(entry = it.next()).done) {
    console.log(entry.value[1]);
}

In this example, the Array.prototype.entries method returns an iterator that is used to display the values of the array. At each iteration the entry.value contains the [key, value] array.

Iterating Over Array-Like Objects

Array-like objects may look like an Array. Such objects even have the length attribute and properties with names in the form of numbers that correspond to the elements in the array. Examples include the DOM NodeList collection and the Arguments pseudo-array, available within any function or method.

Most, if not all, of the ways to iterate through arrays, can be used to iterate through the array-like objects. Which means you can use the for and for…in statements to iterate over array-like objects. You can also use forEach and other Array.prototype methods to iterate over array-like objects. For this, you need to use the Function.call or Function.apply.

For example, if you want to apply the forEach statement to the childNodes property of the Node object:

Array.prototype.forEach.call(node.childNodes, function(child) {
    // Do something with the child object
});

For easy reuse, you can declare a reference to the Array.prototype.forEach method in a separate variable and use it as a shortcut:

// (Assumes that all code is in the same scope)
var forEach = Array.prototype.forEach;

// ...

forEach.call(node.childNodes, function (child) {
    // Do something with the child object
});

If an array-like object contains the iterator, it can be used explicitly or implicitly to iterate through the objects in a manner similar to arrays.

Making the Array-like Objects become Arrays

For this, you can use the generic Array.prototype.slice, which can be applied to any array-like object:

var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);

For instance, if you want to convert the NodeList collection into an array

var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);

Also, ES6 provides the Array.from method that creates a new Array instance from an array-like or iterable object.

If you are using the Array.prototype methods to runtime objects (such as the DOM collection), you should keep in mind that these methods do not work in all environments (including browsers). It depends on the behavior of a particular object in a particular environment. To be precise, it depends on how that object implements the HasProperty abstract operation. The problem is that ES5 standard leaves open the possibility of misconduct of the object in relation to the HasProperty operation. Therefore, it is important to test the array.prototype methods in each runtime (browser) where you plan to use your application.

Tags: Last modified: October 07, 2022
Close