30 Days Of JavaScript.8E
Day 8. Objects_Exercise
👟Level 1.
1) Create an empty object called dog.
const dog = {};
2) Print the the dog object on the console.
console.log(dog); //{}
3) Add name, legs, color, age and bark properties for the dog object. The bark property is a method which return woof woof.
const dog = {
name: 'Toby',
legs: 4,
color: 'brown',
bark: () => 'woof woof'
}
console.log(dog); //{name: 'Toby', legs: 4, color: 'brown', bark: ƒ}
console.log(dog.bark()); //woof woof
Or, I can just put the key-value pair right into the object I made before.
const dog = {};
dog.name = 'Toby';
dog.legs = 4;
dog.color = 'brown';
dog.bark = () => 'woof woof'
console.log(dog); //{name: 'Toby', legs: 4, color: 'brown', bark: ƒ}
I wanted to use an arrow function, but at first I put it in the wrong way like function = () => 'woof woof'
. An arrow function uses an arrow instead of the function
keyword, so the syntax was wrong.
An object method is a function inside an object.
4) Get name, legs, color, age and bark value from the dog object.
console.log(Object.values(dog)); //(4) ['Toby', 4, 'brown', ƒ]
5) Set new properties the dog object: breed, getDogInfo.
const dog = {
name: 'Toby',
legs: 4,
color: 'brown',
bark: () => 'woof woof'
}
dog.breed = 'bulldog';
dog.getDogInfo = function() {
let statement = `This dog is ${this.name}. He has ${this.legs} legs. He is ${this.color}, and he barks ${this.bark()}.`
return statement;
}
console.log(dog.getDogInfo()); //This dog is Toby. He has 4 legs. He is brown, and he barks woof woof.
👟Level 2.
const users = {
Alex: {
email: 'alex@alex.com',
skills: ['HTML', 'CSS', 'JavaScript'],
age: 20,
isLoggedIn: false,
points: 30
},
Asab: {
email: 'asab@asab.com',
skills: ['HTML', 'CSS', 'JavaScript', 'Redux', 'MongoDB', 'Express', 'React', 'Node'],
age: 25,
isLoggedIn: false,
points: 50
},
Brook: {
email: 'daniel@daniel.com',
skills: ['HTML', 'CSS', 'JavaScript', 'React', 'Redux'],
age: 30,
isLoggedIn: true,
points: 50
},
Daniel: {
email: 'daniel@alex.com',
skills: ['HTML', 'CSS', 'JavaScript', 'Python'],
age: 20,
isLoggedIn: false,
points: 40
},
John: {
email: 'john@john.com',
skills: ['HTML', 'CSS', 'JavaScript', 'React', 'Redux', 'Node.js'],
age: 20,
isLoggedIn: true,
points: 50
},
Thomas: {
email: 'thomas@thomas.com',
skills: ['HTML', 'CSS', 'JavaScript', 'React'],
age: 20,
isLoggedIn: false,
points: 40
},
Paul: {
email: 'paul@paul.com',
skills: ['HTML', 'CSS', 'JavaScript', 'MongoDB', 'Express', 'React', 'Node'],
age: 20,
isLoggedIn: false,
points: 40
}
}
1) Find the person who has the most skills in the users object.
console.log(users.Alex.skills.length); //3
I thought this way, I could loop the object and print the array in the form of [userName, numberOfSkills].
let userIds = Object.keys(users); //(7) ['Alex', 'Asab', 'Brook', 'Daniel', 'John', 'Thomas', 'Paul']
for (let i = 0; i < userId.length; i++) {
let userIds = Object.keys(users);
let userSkills = users.userIds[i].skills;
console.log(userIds, userSkills);
}
It didn’t work out. There was an error to userID
that it couldn’t read 0. I guess it is because userId[i]
doesn’t come across as Alex, but ‘Alex’ as a string.
The users
object is composed of another 7 objects by the username, each containing 5 keys(or properties) with a value. What I want to print out is the object name, and the length of skill
value of that object.
I couldn’t figure out why it wouldn’t work, so I asked stackoverflow. From the comments, I could learn that I cannot use dot notation with variables. Instead, I should have used bracket notation to detect a string-named property. Here’s a nice article about the topic: Dot notation vs Brackets? and the MDN Document about property accessors.
//get arrays of [userName, numbers of skills] separately
let userIds = Object.keys(users);
for (let i = 0; i < userIds.length; i++) {
let userSkills = [userIds[i], users[userIds[i]].skills.length];
console.log(userSkills);
}
//(2) ['Alex', 3], (2) ['Asab', 8], (2) ['Brook', 5],...(2) ['Paul', 7]
//get the same array as an array of arrays
let userIds = Object.keys(users);
let userSkills = [];
for (let i = 0; i < userIds.length; i++) {
userSkills[i] = [userIds[i], users[userId[i]].skills.length];
}
console.log(userSkills);
//(7) [Array(2), Array(2),... Array(2)]
//[['Alex', 3], ['Asab', 8],...['Paul', 7]]
To only get the username who has most skills, I set the max number of skills length. Then I printed out the username who has the max number of skills.
//just get the username who has most skills
let userIds = Object.keys(users);
let userSkills = [];
for (let i = 0; i < userIds.length; i++) {
userSkills[i] = users[userIds[i]].skills.length;
}
const max = Math.max(...userSkills);
for (let i = 0; i < userIds.length; i++) {
if (userSkills[i] == max) {
console.log(userIds[i]);
}
}
//Asab
At the code above, I first wrote the condition as userSkills[i] = max
and wondered why all the usernames are printed. =
is an assignment operator, so all the elements of userSkills
became the max number.
=
and==
/===
are different! Let’s be aware of that.
2) Count logged in users, and count users having greater than equal to 50 points from the following object.
let userIds = Object.keys(users);
let countLoggedIn = 0;
for (let i = 0; i < userIds.length; i++) {
if (users[userIds[i]].isLoggedIn == true) {
countLoggedIn++;
}
}
console.log(countLoggedIn); //2
3) Find people who are MERN stack developer from the users object.
A MERN developer should have ‘MongoDB’, ‘Express’, ‘React’, ‘Node’ in their skill property.
let mernDev = [];
let userIds = Object.keys(users);
for (let i = 0; i < userIds.length; i++) {
let skills = users[userIds[i]].skills
if (skills.includes('MongoDB') && skills.includes('Express') && skills.includes('React') && skills.includes('Node')) {
mernDev.push(userIds[i]);
}
}
console.log(`MERN Developers: ${mernDev.join(', ')}`);
//MERN Developers: Asab, Paul
4) Set your name in the users object without modifying the original users object.
users.Ramona = {
email: 'ramona@ramona.com',
skills: ['HTML', 'CSS', 'JavaScript'],
age: 23,
isLoggedIn: true,
points: 30
}
5) Get all keys or properties of users object.
console.log(Object.keys(users));
//(7) ['Alex', 'Asab', 'Brook', 'Daniel', 'John', 'Thomas', 'Paul']
For the case that the quiz was asking for all the keys, including the keys inside the keys, I wrote the code down below. Since all the keys from each user was the same, I just put userids[0]
to specify one key.
let userIds = Object.keys(users);
let userKeys = Object.keys(users[userIds[0]]);
const allKeys = userIds.concat(userKeys);
console.log(allKeys);
//(12) ['Alex', 'Asab', 'Brook', 'Daniel', 'John', 'Thomas', 'Paul', 'email', 'skills', 'age', 'isLoggedIn', 'points']
6) Get all the values of users object.
console.log(Object.values(users));
//return an array that has 7 object elements, each containing five key-value pairs
Again, for the case that the quiz was asking for all the values, including the keys inside the keys, I wrote the code below.
let userIds = Object.keys(users);
const userValues = [];
for (let i = 0; i < userIds.length; i++) {
userValues.push(Object.values(users[userIds[i]]));
}
console.log(userValues);
//return an array with 5 array elements, each containing the values of user information
7. Use the countries object to print a country name, capital, populations and languages.
Since the countries array is an array of objects, I had to set another array variable to consider each element object as an object.
for (let i = 0; i < countries.length; i++) {
let name = countries[i]['name'];
let capital = countries[i]['capital'];
let population = countries[i]['population'];
let languages = countries[i]['languages'];
console.log(`${name}, ${capital}, ${population}, ${languages}`);
}
At first I thought I had to set another array variable to consider each element object as an object. But soon I realized that it wasn’t needed. I could just use an array index, and only print the values of name, capital, populations, and languages keys.
👟Level 3.
1) Create an object literal called personAccount. It has firstName, lastName, incomes, expenses properties and it has totalIncome, totalExpense, accountInfo, addIncome, addExpense and accountBalance methods. Incomes is a set of incomes and its description, and expenses is a set of expenses and its description.
const personAccount = {
firstName: 'Jane',
lastName: 'Doe',
incomes: {
salary: 5000,
onlinecourses: 15000,
parttime: 1000
},
expenses: {
groceries: 1500,
bills: 3000
},
totalIncome(){
const incomesFrom = Object.keys(this.incomes);
let addIncomes = 0;
for (let i = 0; i < incomesFrom.length; i++) {
addIncomes += this.incomes[incomesFrom[i]];
}
return addIncomes;
},
totalExpense(){
const expensesFrom = Object.keys(this.expenses);
let addExpenses = 0;
for (let i = 0; i < expensesFrom.length; i++) {
addExpenses += this.expenses[expensesFrom[i]];
}
return addExpenses;
}
}
console.log(personAccount.totalIncome()); // 21000
console.log(personAccount.totalExpense()); // 4500
Further Study
From this video tutorial, I learned that to write functions as regular functions inside methods, I can take away the function
keyword and the colon, and just have the parentheses directly after the property name like above.
I could also understand this
keyword better. The this
keyword is a context object that represents the context in which the current code is executed. When I call a method that contains this
, JavaScript sets the value of the this
keyword to be the object the method was used on.
2) Imagine you are getting the above users collection from a MongoDB database.
const users = [
{
_id: 'ab12ex',
username: 'Alex',
email: 'alex@alex.com',
password: '123123',
createdAt:'08/01/2020 9:00 AM',
isLoggedIn: false
},
{
_id: 'fg12cy',
username: 'Asab',
email: 'asab@asab.com',
password: '123456',
createdAt:'08/01/2020 9:30 AM',
isLoggedIn: true
},
{
_id: 'zwf8md',
username: 'Brook',
email: 'brook@brook.com',
password: '123111',
createdAt:'08/01/2020 9:45 AM',
isLoggedIn: true
},
{
_id: 'eefamr',
username: 'Martha',
email: 'martha@martha.com',
password: '123222',
createdAt:'08/01/2020 9:50 AM',
isLoggedIn: false
},
{
_id: 'ghderc',
username: 'Thomas',
email: 'thomas@thomas.com',
password: '123333',
createdAt:'08/01/2020 10:00 AM',
isLoggedIn: false
}
];
2-1) Create a function called signUp which allows user to add to the collection. If user exists, inform the user that he has already an account.
2-2) Create a function called signIn which allows user to sign in to the application.
function signUp() {
let userNameInput = prompt('Enter your first name.');
const usernames = [];
for (let i = 0; i < users.length; i++) {
usernames.push(users[i].username);
}
if (usernames.includes(userNameInput)) {
console.log('You already have an account.');
} else {
signIn();
}
}
function signIn() {
const newUser = {};
newUser._id = generateId();
newUser.username = prompt('Enter your first name.');
newUser.email = prompt('Enter your email address.');
newUser.password = prompt('Set your password.', '6 digits of number');
newUser.createdAt = generateTime();
newUser.isLoggedIn = true;
users.push(newUser);
}
function generateId() {
let possible = 'abcdefghijklmnopqrstuvwxyz0123456789';
const id = [];
for (let i = 0; i < 6; i++) {
id.push(possible.charAt(Math.floor(Math.random() * possible.length)));
}
return id.join('');
}
function generateTime() {
const now = new Date();
const year = now.getFullYear();
let month = now.getMonth() + 1;
let date = now.getDate();
let hours = now.getHours();
const minutes = now.getMinutes();
let ampm;
if (month < 9) {
month = `0${month}`;
}
if (date < 10) {
date = `0${date}`;
}
if (hours > 12) {
hours = `${hours - 12}`;
ampm = 'PM';
} else {
ampm = 'PM';
}
if (minutes < 10) {
minutes = `0${minutes}`;
}
return `${month}/${date}/${year} ${hours}:${minutes} ${ampm}`;
}
console.log(signUp());
users
is an array of objects, each containing 6 properties of the user. I made four functions in the code: signUp()
, signIn()
, generateId()
, and generateTime()
. I separated those functions to make sure that one function does one job.
When I execute signUp()
, it will make an array consisted of usernames, and check if the input from prompt
is in the array. If not, it’ll call signIn()
function. The signIn()
function creates a new object, and assign the key-value pairs. I wanted the _id
to be randomly assigned by a function, so I made generateId()
function, which generates 6 digits of random ID. The generateTime()
function assigns the value to createdAt
property. I set the value of isLoggedIn
property as true
for default.
- Search Log
stackoverflow: how to push object into array
3) The products array has three elements and each of them has six properties.
const products = [
{
_id: 'eedfcf',
name: 'mobile phone',
description: 'Huawei Honor',
price: 200,
ratings: [
{ userId: 'fg12cy', rate: 5 },
{ userId: 'zwf8md', rate: 4.5 }
],
likes: []
},
{
_id: 'aegfal',
name: 'Laptop',
description: 'MacPro: System Darwin',
price: 2500,
ratings: [],
likes: ['fg12cy']
},
{
_id: 'hedfcg',
name: 'TV',
description: 'Smart TV:Procaster',
price: 400,
ratings: [{ userId: 'fg12cy', rate: 5 }],
likes: ['fg12cy']
}
]
3-1) Create a function called rateProduct which rates the product.
3-2) Create a function called averageRating which calculate the average rating of a product.
function rateProduct(name) {
for (let i = 0; i < products.length; i++) {
if (products[i].name == name) {
return products[i].ratings;
}
}
}
console.log(rateProduct('mobile phone'));
//(2) [{…}, {…}]
//[{userId: 'fg12cy', rate: 5}, {userId: 'zwf8md', rate: 4.5}]
function rateProduct(name) {
for (let i = 0; i < products.length; i++) {
if (products[i].name == name) {
return products[i].ratings;
}
}
}
function averageRating(name) {
let ratingArr = rateProduct(name);
if (ratingArr.length === 0) {
console.log('Ratings not found');
} else if (ratingArr.length) {
let rateSum = 0;
for (let i = 0; i < ratingArr.length; i++) {
rateSum += ratingArr[i].rate;
}
console.log(rateSum / ratingArr.length);
}
}
averageRating('mobile phone'); // 4.75
averageRating('Laptop'); // Ratings not found
averageRating('TV'); // 5
The ratingProduct
function will return the array of the rating property, which is stored at the variable ratingArr
. If ratingArr
has more than one rating object, the length of ratingArr
will have an integer value. I can use this for a condition, for the numbers that aren’t zero are considered true
.
4) Create a function called likeProduct. This function will help to like to the product if it is not liked and remove like if it was liked.
function currentUser() {
let userNameInput = prompt('Enter your first name.');
for (let i = 0; i < users.length; i++) {
if (users[i].username === userNameInput) {
let userId = users[i]._id;
return userId;
}
}
}
function likeProduct(name) {
let likedUser = currentUser();
for (let i = 0; i < products.length; i++) {
if (products[i].name == name) {
if (products[i].likes.includes(likedUser)) {
products[i].likes.splice(products[i].likes.indexOf(likedUser), 1);
return products[i].likes;
} else {
products[i].likes.push(likedUser);
return products[i].likes;
}
}
}
}
likeProduct('mobile phone');
Normally, the user clicks ‘like’ when they’re logged in, so the computer can access to the user’s id. But I don’t know how to implement that for now, so I made another function currentUser
that checks the current user(similar to login). The function checks who the user is by getting an input of user’s name.
In the case that each likes
array contains all the ids of the users who liked the product, the likeProduct
function will check if the array contains the user id. If the user liked the product before, the likes
array would contain the user’s id, and the function will remove the id(using splice()
). If the likes
array doesn’t have the id, it will add the id to the array.
Though, I thought that the code wasn’t efficient, because it has to check all the elements. If likes
array operates like boolean(whether the likes
array contains the logged-in username or not), I could use the code below.
function likeProduct(name) {
let likedUser = currentUser();
for (let i = 0; i < products.length; i++) {
if (products[i].name == name) {
if (products[i].likes.length) {
products[i].likes.pop();
return products[i].likes;
} else {
products[i].likes.push(likedUser);
return products[i].likes;
}
}
}
}
In the case that the likes
array only stores one user’s like and dislike, the length of the likes
array will be 1 or 0, which is true or false. I can simply push
or pop
the user’s id, regarding the original value.
Leave a comment