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.