A very common issue. Iterating about Arrays is an easy task for most, but when it comes to iterate an Object many developers end up getting complicated and the result is not what the expected.
Iterating an Object is a task that if you have not already passed without a doubt, sooner or later you will pass. So when the day comes, you’d better be prepared.
Dramatisation aside, Objects are structures that store information and unlike Arrays, without any specific order and the keys of an Object can be of any type, so the method you use to iterate an Array will not necessarily work for an Object.
Fortunately Javascript provides a lot of options to iterate over an object. In this article I will show 5 different methods and the efficiency of each one for the same Object.
Basically, what I did was this: I created a simple Object, (by simple, I mean that there are no nested properties) with 10,000 entries, and used the console.time()
method to measure the time each method is executed. The final time is the arithmetic mean of 10 iterations.
The code I used to create the array and measure the times is this:
let obj = {};
for (let i = 0; i < 10000; i++) {
obj['key' + i] = 'val' + i;
}
/*
{ key0: 'val0',
key1: 'val1',
key2: 'val2',
key3: 'val3',
key4: 'val4',
key5: 'val5',
.
.
.
*/
console.time("Object Iteration Time");
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
//body
}
}
console.timeEnd("Object Iteration Time");
For our first example, to iterate an object, you can use the loop for…in
like I showed up there. However, you also have to make sure that the key is a real property of the object, and not a property that comes from the prototype, that’s why i’m using the Object.hasOwnProperty();
.
console.time("Object Iteration Time");
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
//body
}
}
console.timeEnd("Object Iteration Time");
//2.821ms
Using the for…of
method we’ve already managed to delete a few lines of code. In this example, for the same reason of the method above, I used Object.keys()
to guarantee the use of only the object’s own properties without the properties of the whole prototype chain.
console.time("Object Iteration Time");
for (let key of Object.keys(obj)) {
//body
}
console.timeEnd("Object Iteration Time");
//3.912ms
The Array.forEach()
method is classically used for Arrays, but with some adaptations we can use in Objects as well. The Javascript Object class offers several useful methods, one of them is Object.keys()
, which was already used in the example above. The method returns an array of the names of the listed properties of a given object, disregarding the prototype properties. Since the object returns the keys of the Object, to access the values is simple, just use obj[key]
.
console.time("Object Iteration Time");
Object.keys(obj).forEach(key => {
//body
});
console.timeEnd("Object Iteration Time");
//1.972ms
Object.values()
, is also a method of the Object class, which returns an array of the values of the (listed) properties of a given object. In this case, we don’t have access to the original keys of the object only to the values of the object.
console.time("Object Iteration Time");
Object.values(obj).forEach(value => {
//body
});
console.timeEnd("Object Iteration Time");
//8.360ms
The Object.entries()
method returns an array of pairs of listed [key, value]
properties of an object. With this method it is easy to access both the keys and the values of your object, you can do this using, for example, literal templates:console.log(`${key}:${value}`);
.
The order of the array returned by Object.entries()
; does not depend on how the object is defined.
console.time("Object Iteration Time");
Object.entries(obj).forEach(([key, value]) => {
//body
});
console.timeEnd("Object Iteration Time");
//11.887ms
Well, the results I got during the tests were those shown in the table.
Although it is one of the most practical, because it already gives you access to both the keys and the values the method with Object.entries(), it also proved to be the slowest method.
Método | Tempo médio |
forEach() como Object.keys() | 1.972ms |
for..in com Object.hasOwnProperty() | 2.821ms |
for..of com Object.keys() | 3.912ms |
forEach() com Objects.values() | 8.360ms |
forEach() com Object.entries() | 11.887ms |
And the champion in performance got the third method I showed on the list. He has the disadvantage of having to use obj[key]
(as well the methods 1 and 2) to access the values. If performance is something crucial in your project, or if you work with large objects it might be the most appropriate.
In the end, each project may require a different implementation to solve this problem, so it’s up to you, the developer, to know what fits your project best. Till next time
Leave a Reply