How to Iterate Over an Array-Like Object in JavaScript?

To iterate over an array-like object, you can do any of the following:

  1. Use a for loop — this is possible because by definition an array-like object has length and indexed elements;
  2. Implement the iterable protocol — this would make the array-like object iterable;
  3. Convert the array-like object to an array — this would allow you to use loops available on an array.

#Use a for Loop

Since an array-like object has indexed elements and the length property, you could simply use a for loop to iterate over its elements, for example, like so:

const obj = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

for (let i = 0; i < obj.length; i++) {
    console.log(obj[i]); // output: 'foo', 'bar', 'baz'
}

In cases where the indexes have gaps, it would look like the following:

const obj = { 0: 'foo', 5: 'bar', 7: 'baz', length: 8 };

for (let i = 0; i < obj.length; i++) {
    console.log(obj[i]); // output: 'foo', 4 x undefined, 'bar', undefined, 'baz'
}

While a for...in loop can also be used to iterate over the items in an array-like object, it should be avoided because it will also enumerate its other enumerable properties (such as the length property, etc.).

#Implement the Iterable Protocol

Iterables (objects that implement the iterable protocol) are data structures that allow access to their elements in a sequential manner. If an array-like object does not implement an iterable protocol, then it won't work with syntaxes that expect iterables (such as for...of loop, the spread syntax, yield*, and destructuring assignment). For example:

const obj = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

// TypeError: obj is not iterable
for (const item of obj) {
    console.log(item);
}

Conforming to the Iterable Protocol:

An object can be made iterable by conforming to the iterator protocol — i.e. by implementing the next() method (that returns at least done and value properties), for example, like so:

const obj = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

obj[Symbol.iterator] = function () {
    let i = -1;
    return {
        next: () => ({ value: this[++i], done: i === this.length })
    };
};

for (const item of obj) {
    console.log(item); // output: 'foo', 'bar', 'baz'
}

Since the for...of loop expects iterable objects, it is able to access the object's Symbol.iterator function and loop through its properties as per our design.

To give you a better understanding of how the next() method works, let's substitute the for...of loop with a while loop:

// ...

const iterator = obj[Symbol.iterator]();

while (true) {
    const result = iterator.next();

    if (result.done) {
        break;
    }

    console.log(result.value);
}

// ...

Defining Symbol.iterator Property Directly Inside the Object:

It is also possible to define the "Symbol.iterator" property directly inside an object using a computed property like so:

const obj = {
    // ...

    [Symbol.iterator]() {
        let i = -1;
        let self = this;

        return {
            next() {
                return { value: self[++i], done: i === self.length }
            }
        }
    },

    // ...
};

Using a Generator:

Let's simplify the code from the earlier example using a generator:

const obj = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

obj[Symbol.iterator] = function* () {
    for (let i = 0; i < this.length; ++i) {
        yield this[i];
    }
};

for (const item of obj) {
    console.log(item); // output: 'foo', 'bar', 'baz'
}

As you can see from the example above, using a generator as our Symbol.iterator does not require us to explicitly define a function that returns the "next" property, which simplifies the code quite a lot.

Defining Symbol.iterator Property Directly Inside the Object:

It is also possible to define the "Symbol.iterator" property directly inside an object using a computed property like so:

const obj = {
    // ...

    *[Symbol.iterator]() {
        for (let i = 0; i < this.length; ++i) {
            yield this[i];
        }
    },

    // ...
};

#Convert the Array-Like Object Into an Array

It is possible in JavaScript to convert an array-like object to an array. Once you do that, you could then loop over your collection simply as you would with an array using any loop. For example:

const obj = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
const arr = Array.from(obj);

arr.forEach((item) => console.log(item)); // output: 'foo', 'bar', 'baz'

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.