How to Iterate Through JSON Objects in JavaScript
TL;DR
Use for
… in
. It’s fast. It’s clean. It looks nice.
for (let key in obj) {
let value = obj[key];
if (obj.hasOwnProperty(key)) {
console.log(`Property ${key} is NOT from prototype chain`);
} else {
console.log(`Property ${key} is from prototype chain`);
}
}
Not Quite TL;DR
We can’t exactly “iterate” through an object like we can an array since it has no defined order. So, what do we do?
Suppose we have the following object:
// Example object
let obj = {
key1: "val1",
key2: "val2",
key3: "val3"
}
We’ll go over a few ways JavaScript allows us to “iterate” through JSON objects.
Method 1: .entries()
We can use Object.entries()
to convert a JSON array to an iterable array of keys and values.
Object.entries(obj)
will return an iterable multidimensional array.
[
["key1", "val1"],
["key2", "val2"],
["key3", "val3"],
]
We can use this output to find our keys and values in a bunch of different ways.
for (let [key, value] of Object.entries(obj)) {
console.log(key, value);
}
Object.entries(obj).forEach(entry => {
let key = entry[0];
let value = entry[1];
console.log(key, value);
});
Object.entries(obj).map(entry => {
let key = entry[0];
let value = entry[1];
console.log(key, value);
});
Method 2: .keys()
Similarly, Object.keys(obj)
returns an iterable list of keys.
Object.getOwnPropertyNames()
is another way to access an object’s keys.
It’s essentially the same as Object.keys()
.
["key1", "key2", "key3"]
Object.keys(obj).forEach(key => {
let value = obj[key];
console.log(key, value);
});
Method 3: .values()
Similarly, Object.values(obj)
returns an iterable list of values.
In this instance, we won’t have access to the key
associated with each value
.
Object.values(obj).forEach(value => {
console.log(value);
});
Method 4: for
… in
for (let key in obj) {
let value = obj[key];
console.log(key, value);
}
You can also make an optional check for properties in the prototype chain to avoid logging inherited properties.
for (let key in obj) {
let value = obj[key];
if (obj.hasOwnProperty(key)) {
console.log(`Property ${key} is NOT from prototype chain`);
} else {
console.log(`Property ${key} is from prototype chain`);
}
}
We won’t need to check hasOwnProperty()
if we’re using a simple object, or one we made ourselves with {}
.
Which Method is the Fastest?
We’re going to run each method 10,000,000 times to compare performance at a higher scale.
We’ll be using console.time()
to track the time it takes each method to run 10 million times.
function runTest(fn, name, n = 10000000) {
console.time(name);
for(let i = 0; i < n; i++) { fn(); }
console.timeEnd(name);
}
Here, we’re defining a function for each method we described above.
function method1_1() {
for (let [key, value] of Object.entries(obj)) { }
}
function method1_2() {
Object.entries(obj).forEach(entry => {
let key = entry[0];
let value = entry[1];
});
}
function method1_3() {
Object.entries(obj).map(entry => {
let key = entry[0];
let value = entry[1];
});
}
function method2() {
Object.keys(obj).forEach(key => {
let value = obj[key];
});
}
function method3() {
Object.values(obj).forEach(value => { });
}
function method4() {
for (let key in obj) {
let value = obj[key];
}
}
Let’s run the tests!
runTest(method1_1, "Method 1.1")
runTest(method1_2, "Method 1.2")
runTest(method1_3, "Method 1.3")
runTest(method2, "Method 2")
runTest(method3, "Method 3")
runTest(method4, "Method 4")
Here are the results, from fastest to slowest.
"Method 3": .values(): 946.156982421875ms
"Method 4": for ... in: 1364.801025390625ms
"Method 2": .keys(): 1504.135009765625ms
"Method 1.2": .entries(): 11261.76171875ms
"Method 1.1": .entries(): 11572.80419921875ms
"Method 1.3": .entries(): 11719.972900390625ms
Method 3
only has access to the values
, so it never performs any extra computation to obtain the key
. This is why it’s the “fastest” method.
For methods that do have access to both the key and value of an object, Method 4
appears to be the fastest.
Conclusion
It seems that the for
… in
method is the fastest (and, in my opinion, the cleanest) method for iterating through a JSON object.
Keep in mind that object properties are not stored in any order, so when we iterate over an object, we can’t guarantee any order in which they will appear.