Nested object iteration was one of the biggest things I struggled to wrap my head around when it was introduced to me during my first month in Flatiron School. It's not that it is an inherently difficult task or that its this incredibly complex task, I just had the hardest time keeping up with where I was within the iteration. In this explanation I will break it down into small chunks that will hopefully help to better understand where you are at within the iteration.
First things first, there are several ways to access object data in JavaScript:
Use known keys to access the data manually.
objName['keyName'] //=> keyValue
this is useful for user input.
objName.keyName //=> keyValue
used when exact keyName is known.Use built in functions attached to the Object class to access the data.
Object.keys(objName)
//=> returns an array of all keys.
Object.values(objName)
//=> returns an array of all values.
Object.entries(objName)
//=> returns an array of property arrays.Use a for...in loop to iterate over all keys.
For this example we will be using multiple for...in loops to dive down into our nested objects, however for anyone learning about objects I HIGHLY recommend you look up the mdn on the first two examples listed above.
And with that, I'll get right down to the best possible explanation I can give to a newcomer on nested object iteration:
Task:
Lets say we have a toy company split up into two teams that each have a their own individual production and sales departments:
const toyCompany = {
redTeam: {
production: {
'redProdManager': 'Dan',
'redWorkerOne': 'Steve',
'redWorkerTwo': 'Larry'
},
sales: {
'redSalesManager': 'Linda',
'redSalesOne': 'Tony',
'redSalesTwo': 'Matt'
}
},
blueTeam: {
production: {
'blueProdManager': 'Stacy',
'blueworkerOne': 'Kevin',
'blueWorkerTwo': 'Robbie'
},
sales: {
'blueSalesManager': 'Todd',
'blueSalesOne': 'Jess',
'blueSalesTwo': 'Nick'
}
}
};
We've been asked to write a function that finds the job title of an employee given their name as a string.
First for...in Loop:
To do this, we will begin by making our function findEmployee()
and adding our first for...in loop. We will also start by adding a console.log()
in our function to see EXACTLY what our first loop is iterating through. We'll then call the function, in this case we'll be searching for an employee by the name 'Todd'
:
function findEmployee(stringName) {
for (const team in toyCompany) {
console.log(team);
}
}
findEmployee('Todd');
Here is what our console.log(team)
produced:
// LOG: redTeam
// LOG: blueTeam
Lets break this for...in loop down a bit. We can see form the LOG statements that our loop iterated through the first level of objects within the toyCompany
variable, the team names (i.e. redTeam, blueTeam). The for loop is essentially saying:
"for each key on the first level of toyCompany
, I will assign that key to its own variable via const team
and then perform the code below defined within this loop."
In our case, the code below is simple the console.log(team)
. and that is exactly what the code does. For redTeam
, the loop assigned that name to its own variable using const team
and then proceeded to the following code, where we then console.log(team)
. The loop then went on to do the same thing for the next key in that level, blueTeam
. Since there are only two keys, the loop stopped after that.
Second for...in Loop:
So we've successfully made it through the first level, but now how do we get to the next level of objects? That's right! another for...in loop! lets add a nested for...in loop to our function and console.log() the results:
function findEmployee(stringName) {
for (const team in toyCompany) {
const teamObj = toyCompany[team];
for (const department in teamObj) {
console.log(department);
}
}
}
findEmployee('Todd');
Here is what our console.log(department)
produced:
// LOG: production
// LOG: sales
// LOG: production
// LOG: sales
Let's break it down. We've determined that after our first for...in loop we had successfully reached both redTeam
and blueTeam
. Remember that everything that happens inside the {curly brackets} after the first for...in loop happens to one key at a time. So, all the code will be performed for the redTeam
and then all the code will be performed for the blueTeam
.
The first thing we've done is declared another variable, const teamObj = toyCompany[team]
. I know this may seem confusing, but don't overcomplicate it. All this variable is saying is:
"whichever team key I am currently on in my first for...in loop iteration, I will assign all object data inside of that key to the variable of teamObj
."
If you were to console.log(teamObj)
you would see: {production: {...}, sales: {...}}
which is everything inside of either team object, hence the name teamObj
.
This means we have now reached the department level of the nested objects (i.e. production, sales). Now that we can reference the department level of objects via the variable teamObj
, we are set up to iterate through them via the next for...in loop:
for (const department in teamObj) {}
this loop is simply saying:
"for each key on the first level of teamObj
, I will assign that key to its own variable via const department
and then perform the code below defined within this loop."
When we console.log(department)
we see that each department (i.e. production, sales) is logged twice. This is because the first loop starts in the redTeam
and the second loop console log's both production
and sales
. The first loop then moves to the blueTeam
and the second loop runs its code again, console logging both production
and sales
.
Third (and Final) for...in Loop:
Now we can dive down into our final loop to reach the last level of nested objects and find Todd. Lets take a look at the code below:
function findEmployee(employeeName) {
for (const team in toyCompany) {
const teamObj = toyCompany[team];
for (const department in teamObj) {
const jobTitleObj = teamObj[department];
for (const jobTitle in jobTitleObj) {
if (jobTitleObj[jobTitle] === employeeName) {
console.log(jobTitle);
}
}
}
}
};
Our result:
// LOG: blueSalesManager
If you understand how the second loop worked, the third is simply a repetition with a slight change of code at the end. lets walk through it.
Our second for...in loop has gotten us down to the department level of objects (i.e. production, sales). The third loop will get us to the employees. Again we declare a variable const jobTitleObj = teamObj[department]
which assigns a variable to the third level of objects that contains a job title key with a matching employee name variable. A quick console.log(jobTitleObj)
would yield four LOG's, each with an object containing three properties, one for each job within the department. Here's an example of the first of four LOG's:
// LOG: {redProdManager: Dan, redWorkerOne: Steve, redWorkerTwo: Larry}
Next we have our third for...in loop that basically says:
"for each key on the first level of jobTitleObj
, I will assign that key to its own variable via const jobTitle
and then perform the code below defined within this loop."
Again, this is nothing different than the second for...in loop.
Now that we have access to the job title key via the jobTitle
variable, we use an if statement and square brackets to check each jobTitle
key and see what the value is, aka the employee name. We do this by using the object name followed by square brackets with the key name inside (objName[keyName]
). If we were to add console.log(jobTitleObj[jobTitle])
after the third for...in loop, it would yield a list of 12 LOG's with each employees name, showing that we can access the name of each employee using bracket notation.
The if statement is basically saying:
"If the employees name attached to the current key I am on(jobTitleObj[jobTitle]
) is equal to the employeeName
provided when the function was called, then LOG that persons job title (console.log(jobtitle)
)."
and upon calling findEmployee('Todd');
you will see the result as blueSalesManager
which, if we scroll up to our starting data, we see is correct!
Conclusion:
I'll conclude this post by saying that I am very aware there are much more code-efficient ways to go about accomplishing this task, however, for learning purposes as a beginner, this method helps understand the basics of how things are working. It proved to be a rather steep learning curve for myself and probably is for others I can imagine. Hope this explanation helps!
Happy coding and happy learning!
Top comments (0)