Learn Multiple Ways to Iterate Over JavaScript Object Properties and Values

This guide demonstrates multiple ways to iterate over a JavaScript object's properties and values. There are many ways to do this, and each method is slightly nuanced, so for each method we'll provide a detailed explanation, examples, and a description of when it should be used.

1

The first method we'll cover is Object.entries. This method returns an array of an object's string key-value pairs. There are a few interesting ways to use Object.entries.

Iterating with forEach

Using the forEach method, we can access each entry individually. Notice that we are destructuring entry, and entry[0] is the key while entry[1] is the corresponding value.

const obj = {
  'key1': 'value1',
  'key2': 'value2'
}

Object.entries(obj).forEach(entry => {
  let [key, value] = entry;
  console.log(key, value);
})

// output
key1 value1
key2 value2

Iterating with for...of

We can use a slightly nicer syntax to achieve a similar outcome. Using for...of we can destructure each entry in the loop definition.

const obj = {
  'key1': 'value1',
  'key2': 'value2'
}

for (let [key, value] of Object.entries(obj)) {
  console.log(key, value);
}

// output
key1 value1
key2 value2

When should I use Object.entries?

As you can see from the examples above, the most valuable feature of Object.entries is that you have access to both the key and the value. So this is a desirable method to use when you know you're going to operate on the object's properties (keys) and the corresponding values.

Limitations of Object.entries

The main thing to consider when using Object.entries is that it will not return properties in the prototype chain. See the following example:

const someObj = { someProp: 123 };

let newObj = Object.create(someObj);
newObj.newProp = 456;

console.log(newObj.someProp);  // => 123
console.log(newObj.newProp);  // => 456

// Notice that `someProp` is missing here
console.log(Object.entries(newObj));  // => [ [ 'newProp', 456 ] ]

Now, this is probably what we want in most cases, but it's something to be aware of.

2

Object.keys returns an array of an object's enumerable property names.

Enumerable properties are properties set "via simple assignment or via a property initializer". Since JavaScript objects have a lot of additional properties (e.g. constructor, __proto__), we don't want to include these types of properties when operating on our object. They can be accessed directly, of course, but won't be included when iterating over properties.

The usage is simple, see the following example:

const obj = {
  name: 'Levi Coffin',
  birthdate: '10/28/1798',
  city: 'Newport',
  state: 'Indiana'
};

Object.keys(obj)  // => [ 'name', 'birthdate', 'city', 'state' ]

To iterate through the object's properties, we can use forEach:

Object.keys(obj).forEach(key => {
   console.log(key);
});

Or for...of:

for (let key of Object.keys(obj)) {
  console.log(key);
}

And to get the corresponding value, we can use the key for reference. Although, at this point, you ought to use Object.entries from the previous step:

for (let key of Object.keys(obj)) {
  let value = obj[key];
  console.log(key, value);
}

When should I use Object.keys?

As the method name implies, you should use Object.keys when you're only interested in the keys (property names) of an object. If you're also interested in the values, Object.entries is probably the right tool.

Object.keys is especially useful when we're using an object to map data. Consider the following object:

const nameAgeMap = {
  'Tom': 30,
  'Susan': 28,
  'Rob': 35,
  'Claire': 22
};

Object.keys gives us access to an array of names.

Object.keys(nameAgeMap)  // => [ 'Tom', 'Susan', 'Rob', 'Claire' ]
3

Object.values is the counterpart to Object.keys, and returns an array of the object's enumerable property values. We covered enumerable properties in the previous step, and this method simply returns the corresponding value for each enumerable property.

Similarly, we can iterate using forEach:

Object.values(obj).forEach(value => {
   console.log(value);
});

Or for...of:

for (let value of Object.values(obj)) {
  console.log(value);
}

When should I use Object.values?

Again, like its counterpart, you should use Object.values when you're only interested in the object's values.

Using the same map from the previous step:

const nameAgeMap = {
  'Tom': 30,
  'Susan': 28,
  'Rob': 35,
  'Claire': 22
};

We can get the corresponding list of values easily:

Object.values(nameAgeMap)  // => [ 30, 28, 35, 22 ]
4

for...in is similar to Object.keys except it iterates over all of an object's enumerable properties (excluding Symbols).

In the following example, we'll create an object newObj from an existing object obj.

let obj = {
  inheritedProp: 'hello'
};

let newObj = Object.create(obj);
newObj.ownProp = 'world';

In this example, newObj has its own property called ownProp, and an inherited property called inheritedProp. See how Object.keys only iterates through the object's own enumerable properties:

Object.keys(newObj).forEach(key => {
  console.log(key);
});

// output

ownProp

and for...in iterates over all enumerable properties, including those found in the prototype chain:

for (let key in newObj) {
  console.log(key);
}

// output

ownProp
inheritedProp

When should I use for...in?

Because for...in iterates over all enumerable properties, it is distinguished from the previous three methods. Therefore, you should use this method when you're interested in iterating over all enumerable properties (and corresponding values) of an object (not just the object's own properties).

5

Finally, you can use Object.getOwnPropertyNames to get an array of all of an object's own property names, including those of non-enumerable properties. So this is similar to Object.keys, except it includes non-enumerable properties as well.

Let's use an example of an object with inheritance, and we'll explicitly define properties that are not enumerable:

let obj = {
  inheritedProp: 'hello'
};

let newObj = Object.create(obj, {
  'ownProp': {
    value: 'own property',
    enumerable: true
  },
  'nonEnumerableProp': {
    value: 'not enumerable',
    enumerable: false
  }
});

Notice we have an inherited property, and two own properties—one enumerable, and one non-enumerable. If we inspect the object we see this:

{ ownProp: 'own property' }

Now, when we use Object.getOwnPropertyNames we'll get all of the object's own properties, excluding any inherited properties:

Object.getOwnPropertyNames(newObj)  // => [ 'ownProp', 'nonEnumerableProp' ]

And to iterate, just like any Array, we can use forEach:

Object.getOwnPropertyNames(newObj).forEach(name => {
  console.log(name);
});

or for...of:

for (let name of Object.getOwnPropertyNames(newObj)) {
  console.log(name);
}

When should I use Object.getOwnPropertyNames?

This method is distinguished by the fact that it includes non-enumerable properties, so it should be used when this feature is desired.