Well, salam and hello again!
Previously, I discussed array loops, from the basics of the loop to using array loop methods. If you haven't read about it, head to the article straight away! 👇
This time, I want to discuss another loop-related thing, and that is the object. Chotto matte kudasai, the object is loopable too??
Understanding Objects in Javascript
Have you ever wonder what type exists in Javascript? Well, though Javascript is loosely typed language (note that you didn't even need to declare whether your let
and const
is a string
or number
or anything), we can still get what type is our variable is.
To know what type is your variable, just use typeof
.
const name = "Naruto";
console.log(typeof name); // "string"
const team7 = ["Naruto", "Sasuke", "Sakura", "Kakashi", "Sai", "Yamato"];
console.log(typeof team7); // "object"
So, Javascript has 2 general types of variables - primitives and objects. Primitive type includes string, number, symbol, boolean. And, there are objects.
Remember that I told you that array is also an object? Well, that's how it works. An array is an object, with certain features attached to it, that enable several methods along the way like .map
, .forEach
and others. While that is the case that makes array iterable, the native object doesn't have them. That means all array loop methods we discussed before cannot be used with objects.
const character = {
name: "Naruto",
position: "Hokage",
village: "Leaf Village",
country: "Fire Country",
};
character.forEach(); // This will throw error for sure!
So, how do we iterate objects then? 🤔
Back to loop basics
We already discussed a way to loop in Javascript, mainly for
, while
and do...while
. And later, I told you about there are two loops available, one for arrays and one for objects. Do you remember which one is which?
for...of
is for the array. Since the index is in sequence, getting an index is not necessary, unless if you need one.
const team7 = ["Naruto", "Sasuke", "Sakura", "Kakashi", "Sai", "Yamato"];
for (let member of team7) {
console.log(member)
}
/*
The output should be
Naruto
Sasuke
Sakura
Kakashi
Sai
Yamato
*/
On the other hand, for...in
is specifically for objects. Though the loop only fetches the key for you, but you know the rest.
const character = {
name: "Naruto",
position: "Hokage",
village: "Leaf Village",
country: "Fire Country",
};
for (let info in character) {
console.log(`${info}: ${character[info]}`);
}
/*
The output should be
name: Naruto
position: Hokage
village: Leaf Village
country: Fire Country
*/
Well, that's it about looping object..............wait! There is another way as well if you want to use the array loop methods we discussed before. But that means, we need to change our object to arrays, am I right?
Objects as arrays
There are in some dire situations, you had to execute a mission with a different approach. While we already have for...in
for objects, we also have "some other way" to loop object.
Of course, we need to turn the object into an array, so the object can access all goodness offered by array loop methods. Though, in my experience, it's not that much, but pretty useful when you meet other data structures, especially Python that has dictionaries and tuples.
Well, shall we?
Object.keys
If you only need keys in the objects, for...in
already did a good job on that. However, there is a way to convert it to an array with just keys. Using Object
class inside Javascript, we can use methods offered for all objects. YES, I really mean in, ALL OBJECTS! That means, arrays can also use these methods as well, but what for, right?
One Object
method is .keys
, where it will convert to a list of keys of the object.
const character = {
name: "Naruto",
position: "Hokage",
village: "Leaf Village",
country: "Fire Country",
};
console.log(Object.keys(character));
// ["name", "position", "village", "country"]
As you see, the result will be an array. So, do you know where we are heading to? You are right! Array loop methods! You can use all array loop methods, maybe just in case you didn't need one of the properties, or maybe you need to count all letters, or maybe all starts with "A"? Who knows what your use case is, but this is neat, right?
Object.values
Of course, when we talked about objects, we need the values. The method that do the thing is Object.values
.
const character = {
name: "Naruto",
position: "Hokage",
village: "Leaf Village",
country: "Fire Country",
};
console.log(Object.values(character));
// ["Naruto", "Hokage", "Leaf Village", "Fire Country"]
Instead of getting keys, we can straight away get all the values inside an object. Then, proceed with the array loop methods. But how about getting both keys and values?
Object.entries
The last Object
method, that I used most of the time is Object.entries
, since I need both keys and values to execute my functions based on the keys.
const character = {
name: "Naruto",
position: "Hokage",
village: "Leaf Village",
country: "Fire Country",
};
console.log(Object.entries(character));
// [["name", "Naruto"], ["position", "Hokage"], ["village", "Leaf Village"], ["country", "Fire Country"]]
So, what did you notice? Well, .keys
and .values
generate 1-dimensional array, but .entries
generate 2-dimensional array. That means, if I use methods, I still have to call which index it is, right? Like entry[0] and entry[1]?
Destructuring 2-dimensional array
Well, I will write a more descriptive article about destructuring in future, but I will try my best to explain how it works specifically for the array loop method for Object.entries
.
Take an example, where we will have an object, that lists all members of the ninja team in the Naruto era (sorry for non-anime followers, bear with me a little 😖).
const konohaNinja = {
sandSibling: ["Gaara", "Kankuro", "Temari"],
team7: ["Naruto", "Sasuke", "Sakura", "Kakashi"],
team8: ["Shino", "Hinata", "Kiba", "Kurenai"],
teamGuy: ["Rock Lee", "Neji", "Tenten", "Mighty Guy"],
team10: ["Ino", "Shikamaru", "Choji", "Asuma"],
};
See how the object is structured? Keys that contains the team's name, and values that contains all the members of the team. This has been a complex data structure 🥶. So, how should I tackle this solution? Of course, I need to split the team first.
const konohaTeams = Object.entries(konohaNinja);
Now, I can do all sorts of things with this array. What about making a string that says "The members of {team} are {team members}"?
const teams = konohaTeams.map(([teamName, teamMembers]) => {
return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
Chotto matte, what happened here? Okay, I have to admit, there are a lot of things that happened here. So let me go layer by layer.
Remember that when I use .map
, I passed the value for each index? Yes, I do just that. So supposedly, I should write something like this.
const teams = konohaTeams.map((team) => {
/**
* since konohaTeams is a 2-dimensional array,
* (in this case, 3-dimensional array in fact),
* when you loop the object-turns-array, you will still get
* the array, except now you know all subarray has 2 elements
* only, which is key-value pair, given team[0] is a team name
* and team[1] is the array of team members
*/
return `The members of ${team[0]} are ${team[1].join(", ")}`;
});
However, it is hard to read. Maybe you already know what is team[0] and what team[1] stands for. But, is it better, if you can understand what variables are? Of course, there is a better way.
const teams = konohaTeams.map((team) => {
const teamName = team[0];
const teamMembers = team[1];
return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
This is a step better than a previous example. You rename each of the keys and values, then use it in your return. But do you know, that destructuring can do that much for you, and has shorter syntax?
const teams = konohaTeams.map((team) => {
const [teamName, teamMembers] = team;
return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
What happened here? We all already know index 0 equals teamName, and index1 equals teamMembers. Using a declaration way of extracting our array, we can rename each index, so later in our function, we can use those. Shorter and cleaner, right? Okay, can we make it shorter? Of course, instead of destructuring it inside your function, why not we destructure during parameter passing? That is why, now we replace from (team) =>
to ([teamName, teamMembers]) =>
.
const teams = konohaTeams.map(([teamName, teamMembers]) => {
return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
console.log(teams);
/*
The output should be
[
"The members of sandSibling are Gaara, Kankuro, Temari,",
"The members of team7 are Naruto, Sasuke, Sakura, Kakashi,",
"The members of team8 are Shino, Hinata, Kina, Kurenai,",
"The members of teamGuy are Rock Lee, Neji, Tenten, Mighty Guy,",
"The members of team10 are Ino, Shikamaru, Choji, Asuma,"
]
I know, for some beginners, this concept is hard to grasp, but try to take it to step by step, and understand what happens here.
Conclusion
The main point here, it is possible to loop objects as well, as much as how we loop arrays. When converting from object to array, we already provide powers given to arrays and use it for objects.
Of course, there is still a lot of things going on, but if you master how to loop arrays and objects, and how to modify them, either by changing the original one or create a new entity out of them by using array loop methods, I believe you can be a really good Javascript coder at this point.
Well, until next week, peace be upon ya!
Top comments (14)
I deal with this all the time with 3rd party APIs. Many of the ones I use return an object of objects, instead of an array of objects like most normal APIs would do.
Annoying, but not a huge deal when you can just loop a for in/of and push the objects to an array - then perform normal array methods on the data.
This post is relevant for anyone working with older/non standard/shitty APIs
Some API, they prefer putting keys as something that represent the object, such as this
This way, backend can do a better indexing for more data processing. Though I am somewhere 85-92% agree of what you said, some of them had their reason. Though supposely when dealing with API to the frontend, I do favours array of objects instead.
Cheers 😎
Good point. The only apis that return object of objects are old, outdated, and or not maintained in my experience. Which backs up your point - old technology might have needed faster indexing on the backend doing this but now a days just gimme the damn array. 😁
Wow i love reading these articles, it was exactly what i was looking forward to learn, i even paid to advanced js programmers to help me with teachingn me this, but noone could explain it like you. Congratulations!
Glad that this article really help you understand this. Honestly, I struggle with this concept earlier, but struggling rendering lists in React really helps me understand this, especially dealing with various APIs (with some self-ranting along the way).
Maybe some people has expertise, but only some of them have a tact on teaching things. 😁
Very useful indeed, I have also made Package to made it easier npmjs.com/package/@hckrnews/objects
I don't believe that relying on a package for simple object and array manipulations will make things easier.
I think for me making the package was very good for learning to work with objects.
But I agree that it's better to learn how to do it yourself.
Always better to know how to do it in the native way than with a package/library.
But for me this package is also very useful, just so the project code is a little bit cleaner/readable, and reduce duplicate the same tricks.
Just a suggestion, little mistake, you put the image example from object.keys into the object.entries and its duplicated.
Haaaaa! Finally I found the error 😣
Thanks for pointing it out! Fixed them!
You are the man!
Object.entries() with destructuring is friggin awesome
Very nice article. I really liked it. I have also seen your tweets, github profile etc. Are you interested in mentoring/training students? Use the below link to explore and register as a mentor.
mentorif.com/signup?ta=hm_pg_clk_or
Once you register, I'll help you get started.
For getting values in the object we use object.values. So could you fix that mistake in the article?
Can you point it out in which section? I can't pinpoint the error 😅