How to iterate through a JavaScript object

OpenJavaScript 0

Last updated: December 10, 2022.

JavaScript objects – like the one below – are extremely common but frustratingly non-iterable.

myObject = {
    name: "Captain",
    username: "Anonymous",
    password: "weakPassword",
    dob: null,
    sayHi: function() {
        console.log("Hi " + name + "!");
    }
}

Common iteration fails

Try and use a for loop through one, and it will return undefined for each attempt to access a property:

for ( i=0; i<3; i++) {
    console.log(myObject[i]); // undefined
}

Attempting to iterate through it with map will return an error:

myObject.map((item) => {
    console.log(item); // Uncaught TypeError: myObject.map is not a function
})

A for of loop doesn’t work either:

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

And neither does forEach:

myObject.forEach((item) => {
    console.log(item); // Uncaught TypeError: myObject.forEach is not a function
})

So, most go-to iteration methods don’t work with objects. So what are your options?

Option 1: The for in loop

The for in loop allows us to retrieve the keys from a JavaScript object:

let keys = [];
for (key in myObject) {
    keys.push(key); // pushes each key into keys arrays
}
console.log(keys); // [ "name", "username", "password", "dob", "sayHi" ]

Now, to get the values, you can use the value of the key each time the loop runs to query the object:

let values = [];
for (key in myObject) {
    values.push(myObject[key]); // queries object by key each time to get values
}
console.log(values); // ["Captain", "Anonymous", "weakPassword", null, function sayHi()]

To mirror the object format in a single array with both keys and values, create a property in each loop, push the key and property value to it, and then push this array into an array initialized before the loop:

let properties = [];
for (key in myObject) {
    let property = [];
    property.push(key);
    property.push(myObject[key]);
    properties.push(property);
}
console.log(properties); // [ ["name","Captain"], ["username","Anonymous"], ["password","weakPassword"], ["dob",null], ["sayHi",sayHi()] ]

Option 2: Object.entries, Object.keys, Object.values

This in-built Object constructor can create iterable arrays from JavaScript objects. Just pass in an object into one of its methods.

Using Object.entries, it creates an array of arrays containing each property key and value:

const entries = Object.entries(myObject);
console.log(entries); // [ ["name","Captain"], ["username","Anonymous"], ["password","weakPassword"], ["dob",null], ["sayHi",sayHi()] ]

Use Object.keys to get the keys only:

const keys = Object.keys(myObject);
console.log(keys); [ "name", "username", "password", "dob", "sayHi" ]

And Object.values for values only:

const values = Object.keys(myObject);
console.log(values); // ["Captain", "Anonymous", "weakPassword", null, function sayHi()]

Nested properties

Note that using a for...in loop or Object.entries only deals with properties and keys at the primary level of an object.

Usually, this is sufficient, but sometimes you may wish to make an entire object iterable by arrayify it, including its nested properties.

This can be achieved by adding a nested for...in loop that runs if a property value at the primary level is a JavaScript object. In this case, the nested for...in loop pushes nested keys and values into nested arrays, and pushes each of these into the array for its parent property:

myObject = {
    name: {
        first: "Captain",
        second: null,
    },
    username: "Anonymous",
    password: "weakPassword",
    dob: null,
    sayHi: function() {
        console.log("Hi " + name + "!");
    }
}
let properties = [];
for (key in myObject) {
    let property = [];
    /* If the value contained by the property myObject[key] is an object... */
    if (typeof myObject[key] === 'object' && !Array.isArray(myObject[key]) && myObject[key] !== null) {
        /* ...push contents to a new nestedProperty variable... */
        for (nestedKey in myObject[key]) {
            let nestedObject = myObject[key];
            let nestedProperty = [];
            nestedProperty.push(nestedKey);
            nestedProperty.push(nestedObject[nestedKey]);
            /* ...and push each nestedProperty into the property (at primary level)  */
            property.push(nestedProperty);
        }
    }
    /* If not an object, push key and value into an array and push to property */
    else {
    property.push(key);
    property.push(myObject[key]);
    }
    
    /* Finally, push whatever is contained in property to the properties array */
    properties.push(property);
}

From array back to object

If you have used the for in loop or the Object constructor to create an array of arrays containing each property key and value in the nested array, you can convert this back to an object again at a later time by using Object.fromEntries:

const entries = Object.entries(myObject);
const myObject2 = Object.fromEntries(entries);
console.log(myObject2); 
//   {
//     name: "Captain",
//     username: "Anonymous",
//     password: "weakPassword",
//     dob: null,
//     sayHi: function() {
//         console.log("Hi " + name + "!");
//     }
// }

Summary

Using a for in loop to extract the keys or the in-built Object constructor to convert to an array, is it possible to iterate through the data contained in JavaScript objects.

Keys and values can be reconstituted as an JavaScript object from an array of arrays using Object.fromEntries.

Related links: