Transcripts
1. Introduction: [MUSIC] Hey, welcome
to this class. As we all know, learning
any new skill can be challenging and JavaScript
is no exception. JavaScript has such
a wide range of features and things
it can be used for, and this can often
leave beginners in a difficult situation
wondering where to even begin, so this is why I've
created this class. This is Part 2 of the
class building on the foundation you've
learned in Part 1. If you've not taken Part 1, be sure to go through this
class first unless you do have some JavaScript
experience already and want to cover the
topics in this section. If you've not taken one
of my classes before, my name is Chris and
I've been building websites for over 20 years. I've also been teaching these skills for
over seven years, both video classes alongside leading web development
boot camps too. This class has many
JavaScript subjects, including loops and
conditional statements, a deep look of
objects, math, date, and timers along with it
drawing to the canvas. All these topics I've covered in a clear and structured way all while building it practical
projects as we go, including real-world
example use cases and also some mini challenges too along with building a pizza chef game to combine many parts of what
you've learned. This project will
be reasonably big, but we will break it down, so you can see how all
the parts fit together. Later on we will
discover some of the trickier parts such
as async JavaScript, scope, hoisting, and closures. Before finishing off
with two more final project,s we will a
small application called Leaving so soon, which is an exit intent pop-up, which is used to
entice visitors with an offer when they try
to leave your site. If all completing
the class faithfully functioning JavaScript
image carousel. It includes a
project folder which we'll add to as we
progress throughout this class and it
will also develop as a useful reference
in future too. Thank you for your interest in this class and I'll see
you in the first lesson.
2. Project Folder Download: If you've already completed
part one of this class, you can continue on with the exact same starter files
which we used in part 1. This part 2 of the
class we'll begin at Section number 6, all
the way to the end. I'll begin in the first
lesson which is for loops. If you have this,
you're completely good to go for the next lesson. If you're jumping into part
2 without taking part 1, which is completely fine too, but you will need to go
over to github.com and download the starter
files which we are going to be using
throughout this class. Follow the link which you
can see on the screen here. Once you land on this page, click on the green coal button, and then download
this as a zip file. Open up this project folder inside your favorite
text editor. I'm going to be using
Visual Studio Code, but you can use any
which you prefer. This is all you
need to get started , and I'll see you next. We'll begin by taking
a look at for-loops.
3. Share Your Work On Skillshare!: When taking any course, it's really important to
not get in the habit of following along just for the sake of ticking
off another lecture. Take the time to
process each lesson, review the code which you write, and think about how you might approach these
solutions yourself. With this in mind, this
class is project-based, and this gives you
the opportunity to really make something
personal and unique. You don't need to get
too lost and divert away from the class
and you can even take a step back after you've
finished the class and come back and make some
project changes afterwards. This will really give you
a good chance to practice what you've learned
away from the class. Also, remember to share
your project too here on Skillshare and only
will I check it out, but it will also inspire
fellow students too. For more information
on the class project, head into the project
and resources tab, where you can not only
upload your project, but you can also see
other class projects too. With this in mind, I look
forward to seeing what you create and upload
here on Skillshare.
4. For Loops: Welcome back. This section is going to be all about loops. We're going to kick off
things with a for-loop. When we started to work
with arrays earlier, we looked at some
different ways to repeat certain tasks
using these loops. The types of loop we
looked at was map, and forEach, both of
these were array methods. Loops mean we can repeat
tasks a lot easier. Even though there are
different types of loops they generally keep repeating
a task a number of times. Often, the main
difference is how we tell the loop to then stop these map, and forEach loops
were array methods, but loops are not
exclusively for arrays. There's also different
types of loops we can use to be able to loop over pretty much
anything we need to. This video is going to be
focusing on a for-loop. This is how a basic
for-loop looks. It sets out a bit like a
function or an if statement. Notice inside of the brackets
that is two semi-colons. These are used to pass in the free expressions which set
up how our loop will work. Really simple example here is
just to use it to increase the number and we will look at some better examples
in just a moment. But for the first expression, it contains the initial or
starting value for our loop. If we just want to start at a number zero or
increase each time, we set up a variable to
be zero, just like this. Second of all, we have
a condition and here we'll see we have the
number is less than 10. This condition determines if
the loop is to keep going. If this is true, the
loop carries on. If false, the loop
will then end. Lastly, if we don't do
something on each loop, the second condition
will always be true. Here we increase the value of the number by one on each loop. Therefore we can
check the condition after each one of these changes. To run through this example
after each loop runs, the number will be increased by one until it reaches number 10, causing the second statement to be then resulting in false, causing the loop to then end. Meaning this particular example, we'll log 10 values, which will be zero
through to number nine. If you have the variable already declared outside
of the for-loop, you can leave out
and just include the second and third statements, and things will still
run the same as before. Also, it's worth
noting you will see lots of examples with
the variable name, the letter i, which is short for
initializer or initial value. This generally is if we're only using this variable
for the purposes of the loop and not needing a descriptive variable
names elsewhere. Note, we must still keep the semicolons in
place so we can clearly separate these three
values onto some examples. Let's jump into
our starter files. For this section jump
into Section number 6, which is loops and conditionals. The first lesson,
which is for-loops, jump into the index page, which is pretty
much empty for now. Then we'll copy the path to this and then paste this
inside of the browser. We have no content
at the moment, just the for-loops title, and then the empty script down at the bottom for us to work in. Let's jump inside of
the script section and we can start to create
our first for-loop. As we looked up before, we use the for keyword, bracket start our
free statements, and then the curly braces. For this example, we're
going to simulate somebody eating a pizza
with 10 different slices. Then we'll deduct a pizza slice after each one of these loops. First of all, our
initializer or our variable, which we'll call slices. We'll set this to be
the initial value of 10 and the next we'll keep
the loop running as long as these slices is
equal to or greater than the value of
one add a semicolon. Then we'll deduct the value of slices by the value
of one each time. Now just to recap, we're going to start off with 10 slices or the value of 10. Then after the loop is finished, this will deduct a slice
to then be equal to nine, nine is greater or equal to one so the loop will
therefore keep running. Then it will run a second time. Then this will deduct
the pizza slices to be eight and then seven, then six. It will keep running until the value is greater
or equal to one. Inside of the curly braces, we add the code which
you want to run. Grab a simple example, we can do a console log with
the value of slices. This is going to
be deducted from 10 all the way down to one. After this, a second
console log with the text of each slice. We can also add things like conditional statements
inside of here too. This conditional statement
is going to check if the slices is equal
to the value of one. If it is, we'll in place in a console log with the
text of no slices left. Let's save this and jump
into the Developer Tools. right-click and "Inspect"
into the console. We see the value of 10 on the first loop is then deducted by the value
of one each time. We get all the way
down to the value of one and then it takes
a note of slices left. Something you may see,
but probably not as much is a second value missing, which is this condition. We do need to leave
in the semicolon in place though and
before we test this, you may be already
spotting a problem. If you have no condition. We have no way of
stopping a loop. This will just keep
running infinitely. This is something we
need to be careful of when creating loops. We must make sure that
the loops condition eventually becomes false. Otherwise, we would end
up in an infinite loop, which would therefore cause
the browser to crash. Don't do this and don't follow
along with this example. But I'm going to show you what happens inside the browser. If we save this, refresh. We see the loop runs
thousands of times, which takes up all of
the browser's resources, causing it to eventually crash. To avoid this crushing
or this infinite loop, we need to manually
use the break keyword inside of the loop when
we want it to then stop. For example, if we go
to this bottom section, we know inside the if statement
this is the last loop. What we can do is we can
add the break keyword. This then break out
of the loop and then stops the
code from running. We can test this by opening
up the browser once more. Open up the Index Page, and then jump into the Developer Tools and
the console and our loop, it now works as expected. Another useful thing
we can do with for-loops is to create
multiple elements, such as list items. Using a loop, we can
create, let's say, 10 elements with a lot less code than we would do if we
wrote this out 10 times. Let's do this just
inside the script, will create a
constant called ul, where we'll create a
new unordered list. We do this with
document.createElement. Passing in the ul elements
which you want to create. Just before we jump into
creating the list items, we'll append our unordered
list to the body. Grab the body with
document.body.appendChild, passing in our ul variable. Just going back to what
we looked at before, we're going to modify
our pizza example and replace this with
the variable name of i. Remember i is a common
naming convention for a variable inside of a loop. We'll initially set this
to be a value of one. We're going to do this in
the reverse way from before. We'll start with the
initial value of one, and then we'll keep
the loop running while i is less than or equal
to the value of 10. Therefore, we need to increase this by the value of
one on each loop, which will cause the
loop to run 10 times. We can move all of the
contents from inside here and then create
our list items. Let's create our list
item we'll select the document.createElement
pass in the list item. Store this inside of
a constant called li. This will then give us
an empty list item. We need to then
place the content inside of the opening
and closing tag. We can do this with
documents.createTextNode, and we can place
in any sample text we want to inside of here. Rather than a regular string, I'm going to insert a
variable using the backticks. We'll say list item placed in our variable with the $ symbol and
the curly braces. We know from above we
have a variable called i, which is equal to
the value of one. Then if you keep increasing by the value of one for each loop. We can check this out by
placing this inside of here. This should start with the
value of list item one, list item two, and so on. All this inside of a
constant, say text. Then we can merge these two together by accessing
the parent, which is the list
item use appendChild. Then place our text inside
of the list element. Finally, when we create each
one of these list items, we then want to push us
to our unordered list. In the same way as we
did with our list item. We select our unordered
list appendChild, where we pass in our list item. Let's check this out,
refresh the browser. This just needs to be i to
match the variable refresh. Now we see the
value of list item one all the way through
to list item 10. As you can imagine, if we
created this 10 separate times, this would result
in a lot more code. Using this loop makes it
a much shorter example.
5. For...in & For...of: We're now going to cover
two more types of loops, which is called for-in
and also for-of. They do look pretty similar and they both loop over something
as you would expect, but the key difference is
what they can loop over. Let's open up the starter
files and see what we have. Into the sidebar, jumping to lesson Number 2
in this section, which is for-in and for-of, and then open this up
inside the browser. First of all, we see a
for-in section which has a product object with various
properties nested inside. As you may expect, this is
how a for-in loop works. We use this type of
loop to loop over the properties
inside of an object, such as the name and the size. Now, this will have
the for-of section, and this is used to loop
over iterable objects. An iterable object is basically some of them
we the loop over, such as an array or a node list. Let's begin up at the top
with our for-in loop, and and we're going
to use this to loop over our product objects. We can do this just below. This looks a bit
like our for-loop from the previous video, we set up the for keyword, the brackets and then
the curly braces. Jumping to the first
set of brackets, and this is how a
for-in loop works. We set up a variable, and we'll call this property
since we're looping over all of the properties
inside this object, which is in our product object. This is where the term
for-in comes from, we have the for
keyword and then the in keyword inside the brackets. We're looping over this full product object and then we're storing the value
of the property inside of this constant. Let's see what it
looks like with a console log of the
value of our variable, which is property, refresh, and we see the value of SKU, the name, the size,
and the color. This gives us the
value of the key, but what about the
actual property value such as cool shirt, medium, and also blue? Well, we can also do
this by accessing our product and then using
the square brackets. Let's take a look at how this looks inside
of a console log. We can use the back ticks
to insert a variable, and we'll start by inserting
the value of property. This is just the
keys which we'll see already inside the console, but afterwards add
a colon to separate this and then insert
our second variable. The second variable is going to be each one of these products. We'll grab the product, and then we can use
the square brackets, to narrow this down to
a particular property. We're passing in
the value of SKU, name, color, or size. If we save this and refresh, we've now created a new string for each one of
these properties, which includes both the key and also the value
of the property. This is how a for-in loop
works to loop over an object. Let's now take a look at for-of. I want to comment out
this section and then go down to the bottom
below our permissions. Again, this begins with the
for keyword, the brackets, and the curly braces, and it also takes in a variable. Let's say const value, which is going to be set to each one of the values
inside of the array. This time rather than using
the in keyword we use of, and then pass in exactly
what we want to loop over. In our case, it's the permissions
array from just above. This is in permissions, and then inside of
the curly braces, we can access our value. On the first loop,
the value is user, the second loop is editor, and then admin,
save and refresh, and there's our three
values inside the console. As you can see inside of
his comments at the top, things like a node list can
also be looped over too. Remember, when we
use something like query selector all to
get multiple elements, a node list is what we get back. To try this out, we also need
some elements to loop over. I'll jump outside
of these scripts, create an unordered list with some sample list
items just inside. Let's duplicate this two more times instead of
spin Number 2 and 3, and then we can loop over
our three list items, which will then return
back a node list, therefore, we can
use the for-of loop. Step 1 is to access all
three of these list items. I'll just above our for loop, create a constant call links, grab these with
document.querySelector, in fact, we need querySelectorAll
since we're accessing multiple elements and once
you grab our list items. Now, rather than accessing
our permissions, what we're going to do
is to access all links, which is our three list items and then change the
variable name to the link. The value of link on our first loop is
the first list item, and the second list item,
and then the third. We can do anything we
want to with these links. For this example,
I'm going to access our links and then
use addEventListener. Listen out for a click
on any of these. This will then run a function, we're going to pass in
the event information , create an alert. To access the contents
inside of each one of these list items
such as 1, 2, and 3, we can do this by accessing
the events information, select e. target, which is the information about that particular list item
which was clicked on, and then display the
innerHTML of that element. Let's try this out.
Now, if we refresh, have our free links at the top, let's click on Number 2,
there's the innerHTML. Number 3, and also Number
1 works correctly too. This is a couple of
really useful variance on the for-loop, which we can use to loop
over things like arrays, and node list, and
also objects too.
6. While & do...while: In my opinion, while
loops look a little simpler than the four loops
that we looked up before. The basic setup looks again similar to many other
things in JavaScript, such as a basic function and if statements and even
the for loop too. A while loop will
keep running as long as a condition
is set to true. For this example, we have
a simple number variable and then the loop
will keep running while the number
is less than 30. This check is performed before the code in
the loop is run, so if it's false the
loop will then stop. As with the for loop, we also need a way of actually stopping things so it doesn't turn
into an infinite loop. We do this inside of the
loop by incrementing the value of the number
by one on each loop. Meaning it will run 30
times before it then stops. Let's head over to our starter
files and give this a try. The next lesson which
we need is number 3. It is the while loop section. Open this up, and also
inside of the browser too. As you can see, we have
an empty starter file with the script at the bottom. What we'll do inside of here is set up a couple of variables. First of all, a constant
called stadiumCapacity, and set this equal
to a value of 100. This is the stadium
capacity and next we'll set up a second variable, which is going to
be for the number of fans which we've
currently entered. Since this can be increased, we need to use the keyword and set this equal to a
value of currentlyEntered, which will begin at
the value of zero. What we want to do is to keep running a loop while the value of currentlyEntered is less
than the stadiumCapacity. A while loop is ideal for this. We set up our while keyword, the brackets, and then the
curly braces just afterwards. What we're going to do
is to keep this loop running while the value
of currentlyEntered, which is zero, is less
than the stadiumCapacity. Basically, if zero
is less than 100, the code inside of
here will then run. Placing a console log
with a text of enter, and we should be
able to go over to the console and check this out. But just before we do this, let's take a step back and
take a look at this loop. If we think about
this, we want to take a look at our condition where they currentlyEntered is less than the stadiumCapacity. At the moment, we have no way of changing these two
variable values. Basically this will always
be the value of true. This will then result
in an infinite loop and again cause a crash
inside the browser. To only run this while loop
a certain amount of times, we need a way of
increasing the value of currentlyEntered on each
loop. This is pretty simple. We just access our value
and then use plus plus, which will increase this
by the value of one on each loop all the way
up to the value of 100. Once this gets to the value of 100 this condition will
no longer be true, meaning this will then
cause our loop to stop. Let's check this out
inside the browser, refresh and jump
into the console. Good and we see
our text of enter has been repeated 100 times. The variance of this
while loop is do-while. This is a switched around
version of this while loop. Before inside the slides, I did mention that the
code inside of this loop will always run after this
condition has been checked. Basically, if this
result in false, the code inside of this loop
will never run even once. We can flip this and make sure that the code runs at least once and then perform
the check afterwards. This is useful if we want to always make sure
that the code runs at least once before
the loop has stopped. To do this, just above our while section we'll
create a do section. We'll say do, open
up the curly braces, and since we always
want this to run once, we just jump straight
into the curly braces, we don't need to
add any condition. Then we can grab our code from the while loop. Cut
this out of place. Add this into the do section. I'm going to remove the curly
braces from the while loop. As you can see, the code now sits inside of the do section, meaning this will
always run at least once before we even
perform our check. Our check is still true, this will keep running
the second time, in our case, all
the way up to 100. Let's check this. We can save this and refresh the browser. We still got the exact
same results as before. We can test this by
setting the value of currentlyEntered to be 100, which then sets
this to be false. If we now save this and refresh, we see our single
console log value of enter because our code runs first and then it will perform the check inside
of the while loop. This is just an
alternative depending on if we always want
the code to run first or to first test the condition before running
any code inside of our loop.
7. If / Else Statements & Nesting: For this video jump into the if-else statements section and also open this up
inside the browser. You can see at the top we
have a user object already setup and also if
statement just below. So we've used if
statements a few times already during
previous examples. There's not a lot more to add to them than what we've
already covered. They simply run some code
between these curly braces. If the condition inside of
here is set to be true. Using this example, we have
a user object at the top. This would result in true since we have an object present, meaning our console
log will work. If the user was logged out, it would maybe set our variable to be null, just like this, so that user to
be equal to null, which would result
in a false value and the code inside the if
statement would not run. So here we are handling
if the condition is true. But what about if
we also want to handle if the
condition is false? Well, this is where else
statements come into play. We place these immediately after the if statement and
this block of code will run in all of the cases which are not covered
by the if section. We have this similar
examples setup inside of the starter files and here we only handling the condition if the
user is logged in. You may be thinking,
why not just handle the logout
condition below this. Or we could do
something like this. We could do a console log
or any code you want to, where we can say the
user is logged out. Well, let's test this out
and see what happens if we refresh and jump
into the console. Here we can see the
console log has run twice. We have the user
is logged in and also the user is logged out. So obviously for something
security sensitive, like a user being logged
in or logged out, we only want one of
these conditions to run. This, we can set up
our if statements, which we have above, followed
by the else statement. Let's remove the console log. I'm placing the else section and add our code inside of here. Let's refresh and we see
user is logged in since we have a user object
present at the top. If we also then change this
to be the opposite and set the user to be equal
to a false value of null. This should then be
user is logged out. If we wanted to, we could also add in multiple if statements to and let`s just push our else statement
down to the bottom. Then in-between we can add a second if statement,
just like we did above. We can check a second condition
such as a user or role, which is currently set to admin. We can check if this is a particular value and if it is inside the curly
braces we`ll do a console log, say, Hey admin,
test this, refresh. Now we see the user
is logged in and they also the admin role. This works, but this also
presents a problem too, we need to be really careful
with this kind of setup. Because this else statement, which we'll have
down at the bottom immediately follows the
second if statement. This means now the
else section will only run if the user's role
is not set to admin, which makes no sense. So we had a user such as null, so with the we're not logged in. Refresh. This will now
throw an error since we are trying to access
the user dot role, which is no longer
available because we no longer have our user objects. For this kind of use
that example to make it a little bit more sense
and to be more workable, we only want to check
if the user's role is equal to admin, they actually logged in. To do this, we can
nest our if statements by cutting out the
second if statement. We can paste this inside
of the first one. This brings us back
to the first example. We have two top-level checks. We have the if statement, the user is logged in followed by the else section just below. Then the if statement
which is nested inside, will only ever ruined if the
user actually logged in. If the user is logged in, this console log will run. Then if they happen to be also logged in as
the admin role, the second console log will also run too. Let's try this out. Refresh, and the
error is now cleared. We see the user is logged out because the user is set to null. Let's reinstate this,
the name to be equal to anything on the
role back to admin. With this now in place,
we now have a user. So the first console
log should run. We also have a user role
which is equal to admin. We should now see two
console logs inside of here. This is how we can use
top-level if else statements and also how we can nest an
if statement inside too. If you wanted to,
you could also go even further end just after
the nested if section, we could also place
in an else section too so we could
do a console log. For this section,
we know the user is actually logged in, but we'll want to also check
if they are not the admin. So here this will run
if they are the admin. Otherwise, we'll just
say, Hey user, refresh. We still see hey admin since
the role is set to this. But if we change this
to be subscriber, the nested if statement
is now false, meaning the hey user
section will now run. If you want to. You
could also go as deep as we wanted to by nesting multiple if else sections
inside of the nested ones too. But we must be careful not to go overboard and make the code hard to read and also to understand
for other developers too. As a general rule, we can
usually cover most use cases without needing
to go to deep. So if you find
that you are maybe three or four levels deep
with if statements or checks, there's usually a better
way to do things.
8. Else if: Inside of this lesson's folder, which is the else if section, you'll find just below
inside the script we have the same example from
the previous video. Here we are handling two top-level conditions
we check in. First of all, if the user
is logged in and then else section capture what happens if the user is not logged in. Inside the logged in section, we also have a nested
if else section too. Add a different greeting if
the user is equal to admin. We have two options
at the top level and also two nested options too. But what about if we
wanted a third option too? For this, we also have else if. Let's take a look at this,
we're going to simplify this example by removing
the nested statements. Inside of here, we'll
remove the nested if else leaving us with a simple
logged in or logged out. If you remember from
the previous video, we took a look at how
to briefly handle a third condition by adding a second if statement,
just like this. But the problem this gives
us is the else section is now connected to our
second if statement. Essentially, meaning
our first if statement is now disconnected. If we still want to
keep all three of these connected unrelated
to each other, we can turn this second one into else if, some place else. Just before the if section, then we can add a second
condition inside of here. First of all, we want to check
if the user is logged in, and then using the
double ampersand, we can also provide
a second check. We can check if the user.role
is equal to subscriber, and if it is, we'll then run
the code inside of here. Now we'll just place in a
simple console log saying the else if section has run, save this, and then over to the browser and we'll see
what happens inside of here. We see the text of
user logged in. You may be wondering why we
see the text of only user logged in and not also
the else if section has run because after
all the user is present and also the user.role
is equal to subscriber. Well, the reason is because only one of these
sections will run. If condition has been met, the code inside will
run and it won't go any further down the rest
of these sections. Effectively, only the
first match will be run. If we want it to be more
specific with the first section, we could also copy
this user.role drop this into the first section and we can also check if
this is equal to admin. Since our user role is
equal to subscriber, they should now be false. Because nowhere else
if section to now run. Let's save this and test
this out in the browser. The else if section
will now run. Since this is our first section which results in through, so now we can do
whatever we want in each one of these sections, we can show and hide content depending on the user's role. We can redirect them
to an account area. We can disable features which the user may
not be allowed to access or anything else
you can possibly think of. We can also use multiple
else if sections too. If we wanted to check more
than these three conditions, we could also do the same just after the else if section, placed in a second one. It's probably conditioned
from just above. This time, we'll check
if the user.role is equal to author. If it is placed
in a console log, give this a save and
as you would expect, we should see the
same result as before since we have the
subscriber set, which is a match
for this section. But if we now change
this to be the offer, the if section is
now false and then the first else if section is also false and our new console log with
the text of author, would now run
inside the console. Finally, if none of these, if or else if sections are true, so we change to be
something like user, we should now fall back to use the else
section down at the bottom.
9. The Switch Statement: Switch statement is
a way to provide as many outcomes as we need
based on a single condition. We can also provide
multiple outcomes with if statements and if else statements like we
looked at previously. But as we discovered, we need to add something to
check against for each one of these conditions such
as when we check things like the user's role for each
one of these conditions. With a switch
statement, however, we just test against the
same condition for each one. Just here with our
favorite pizza variable. The switch statement
just below, again, looks similar in its
setup to things like empty if statements
and also for-loops. We then pass in what
we want to check, such as our favorite
pizza variable. Then inside, we then set up the different cases to handle
what the favorite pizza is. Here we'll have three
separate cases to handle what to do
for each value. We can have as many of
these cases as we want to. Let's look at the first one. We check if the favorite
pizza is equal to pepperoni. If it is, we then run
some code inside, such as this console log. We then provide the break
keyword to break out of the switch statement
once we have a match and this will stop all
the rest of the code and all of the rest of the
checks below from running. This is the same break
keyword we used earlier in this section to avoid the browser creating
an infinite loop. This will keep running
until a match is found, but if one cannot be found, we can also add a
default clause too. This will always run if
there are no other matches. Over to the project and
let's give this a go. This time we're in the
switch statements section and inside the starter file, we'll just have a
simple user object with the name property
and also the role. We can set up a switch
statement to check the user's role and decide if the user can edit
something on our site. This, we can start it in a
variable called canEdit. So canEdit is going to be initially set to
a value of false, so the user is not going
to be assigned any editing permissions by default. Then we can use a
switch statement to check the particular
role of the user. If the particular role
of the user is equal to a higher level such as the
admin or even an editor, we can then set canEdit
to be equal to true. Just like we've
seen in the slides, set up our switch
statements and then we'll pass in the condition
which is user.role. Open up the curly braces, then we can add our
cases inside of here. The first case is
going to be the user. This is just a regular
logged in user. Add the colon. Then
afterwards we add what we want to do for
this particular case. Well, in our case we want to
keep canEdit to be equal to false since they don't have the admin or the
editor permissions. If this particular case
happens to be true, I don't want to use
the break keyword to break out of the rest of
this switch statements. That's the first section. Then we go down to
the second case and this one is going
to be a subscriber. This would just mirror the
same condition as above. We can set canEdit be equal to false. Add the break keywords. That's our second
case now complete. The next one, we'll add
a case for the editor. And as it sounds, the
editor is a case where we want to allow the user
to be able to edit. For this, we'll set our canEdit variable
to be equal to true, then break out of the
switch statement. Finally, the last case is
going to be for the admin. In the Admin we do
want to provide all the permissions which they need to then edit our site. Just like above, we'll
set canEdit to be also equal to true and then break
out of the switch statement. As we'd have seen in the slides, we also need to add
a default case, which is going to be run if none of the cases
above is a match. Very simple example,
just place in a console log and we'll say the user role cannot be found. We'll also set canEdit
to be equal to false. Now we just need to
give this a test. When we first started
off here we have the user role to
be equal to user. This should set canEdit
to be equal to false. Let's test this out by
going down to the bottom, we'll placed in a console log, place in the value of canEdit. We'll see if this changes
for each one of our cases. As we know no canEdit will
be equal to false since we currently have the user
role to be equal to user. Let's jump into the developer
tools into the console. It's false as expected. Let's check our
second condition by switching the role
over to subscriber, refresh and as you would
expect, this is false. The third one is the editor, this should now be true. Finally, we can
test out the admin. This is true also. Just to catch the default condition
down at the bottom, we should see the
console log and they canEdit be equal to false if we don't have a match for any of these four conditions. Let's turn this to be
something completely random. We'll just type in any
random role inside of here. Refresh. This is false and the console log is
now run as expected. Just one thing to
watch out for if we have multiple matching cases. If I have two or more
cases that both match, the first matching
case will be used. Also as a shortcut if
we have multiple cases, just like we have here, which
run the same code inside. The user will set,
canEdit to be equal to false and also the subscriber. This is a duplicated section, the same for the last two cases. Both of these set canEdit
to be equal to true. We can shorten
this code a little bit to make it a
little bit simpler. For the first two, which
are exactly the same, what we can do is remove the
code from the first one. Both of these cases
immediately follow each other. Then this code just
afterwards will run for each one of these cases. The exact same for these
two down at the bottom. We can move the canEdit
and also the break. These two are essentially
now grouped together. We can just test this
out and if we refresh, we still see the default
clause run at the bottom. Let's try the editor.
It should be true. The admin true also. The user should be false. Finally, the subscriber. This is it for the
switch statements. Just one quick thing
before we move on. If we forget to put a break keyword in any
one of these cases, all of the following
cases would also run too until a break
is finally found. For example, if we had missed a break clause inside of this section, we
can remove this. If we have a match
for the user or the subscriber, canEdit will still be equal to false but it would then run the
code it just below, and then override the
canEdit to be equal to true. Let's try this. We have the
role equal to subscriber. Refresh. Now the
subscriber canEdit has taken effect but the
program has kept going down to the editor and also
the admin section and cause an override so
canEdit is now equal to true.
10. Conditional Operator (ternary): As an alternative to the if-else statements
which we've looked at, Javascript also has a
conditional operator, often referred to as
the ternary operator, since it's made up
of three parts. Since it works,
just like if-else, the main reasons why
it's used is to offer a simple single
line alternative. Looking at this user object, we may want to check
the user's age before allowing them in. The conditional operator
can help with this. It's set out like a question. Here we're asking if the
user's age is greater or equal to 18 using
the question mark. Before, I said that the ternary is made up of three parts. The question is just
this first part. The second and third
parts are what we want to do if the question
is true or false. If true, we can do anything but this simple example just
has the text of enter. If it's false, which is
correct for this example, the code after the
colon will run instead. Let's now head over to the
starter files and we can take a look at the
example inside of there. Here we have an example of how we can use an
if statement to check if a user is admin who can edit
something on our site. The user object has
the role of admin, and currently we set the
canEdit functionality to be equal to false. The if statement is checking
if the user's role, which is just here,
is equal to admin. In our case, we can set the
canEdit variable to true, allowing the user
to go ahead and publish something
like a blog post. If not, canEdit will
be equal to false, removing any permissions
which they may have. What we're going to
do is to convert this example to make use
of the ternary operator, which is going to simplify this example onto
one single line. Just like we've seen
in these slides, the first part is to
actually ask the question. The question we
want to ask is if the user.role is equal
to the string of admin. Use a question mark, followed by our true and false outcomes. If the user is equal to admin, we want to set this canEdit
to be equal to true, just like we do in
the true section in the if-else statement. Set canEdit to be equal to true, then separated by a colon, we add the false
statement where we say canEdit to be equal to false. Sometimes depending on your text editor settings or plugins, you may also see
these two statements wrapped inside of the brackets. This is completely fine. What I want to do
now is to comment out or remove the original
if-else statements, and then we can save this
and go over to the browser, refresh, and we see this
example is set to true. This is true because the
user.role is equal to admin. But if we change this
to be something else, let's try subscriber, you should update this to
be the value of false. We can also shorten this
example even further too by directly assigning
the outcome of this ternary operator
to this variable. What we mean by
this is rather than assigning canEdit to be
equal to true or false, when cut the full conditional
operator out of here, we can then remove the
initial assignment of false, paste this in. Now rather than
setting our variable, what we do is simply set the
true value to be equal to true and the false value
to be equal to false. Now the true or false
result to this will be directly assigned to
our canEdit variable. Let's test this
out one more time. Currently we have
this set to be false, but if we change this
back to be the admin, this is now equal to be true. Both the conditional
operator and the if-else version are both
perfectly valid to use. The conditional operator,
as we've just seen, is usually shorter and
placed onto a single line. Some argue that an
if-else statement is more clear and more readable, but in the end, it's your
choice which you want to use, and which one you prefer.
11. Type Coersion & Conversion: In the upcoming few videos
we're going to cover some type and also some true
or false related things, which can give you some
strange or unexpected results. Being aware of these
could help you understand things like why and if statement is not
running correctly, and also save you lots
of time debugging. The first one is type coercion. We already know
about types such as objects, strings, and Booleans. Type coercion relates
to how the values of datatypes are converted
to other data types. Looking inside the
lessons folder which is type coercion and comparison, jump into the index.html where
we have a simple example. We have two variables at the top with numbers and
then we're going to add both of these
together and store them inside of the total. One thing to notice between these two numbers
is the first one is wrapped inside these quotations so technically this is a string. The second one is a number,
as you would expect. But what do you think
happens when we add both of these together? If we were adding together strings we may know
what to expect, because this may be
combined to make a sentence or a word. If we're also adding
together two numbers, these two numbers would be added together to make a new total. But here, since we are adding
a string and a number, what do you think will happen? Well, rather than
cause an error, JavaScript is designed to choose one datatype to convert
to automatically. This is called coercion. But this example it can
choose to convert so they are both strings or they
are both numbers. Well, let's not guess. Let's save this and
go into the console and see exactly what's
going to happen. Jump into the console tab and refresh and we see
the value of 72. The value of 72 means that this is being
converted to a string because we have the value of seven followed by
the value of two, rather than the value of nine, which would happen if these were converted for both
to be numbers. This conversion has happened automatically for us and
this can be referred to as implicitly and this implicit conversion
is what coercion is. Not to be confused,
but something similar is type conversion. This works similar to
coercion by converting a value from one data
type to another. But we can also do this
ourselves manually. If we wanted this to be
converted to a number manually, we have a number
function available. The way we can use this is to cut our number one,
which is a string. We can access a number
function and then place inside what we want to
convert to a number. Here we convert a
string to be a number. Now if we save
this, we should see the value of nine
in the console, meaning that both of
these attract as numbers. To recap, coercion happens
implicitly or automatically. Type conversion can also
happen manually too, just like we're seeing
with this number function. Sometimes these words are
used interchangeably, but this is the official
line on both of these. If you wanted to, we could
also do the opposite. Rather than converting
this one to be a number, we could convert the
second one to be a string. We do this with the
string function. Pass in the number which
you want to convert to a string and this
would then return back to the string value of 72. For this reason, it may
be good to always convert incoming data to be exactly what data type
we want it to be. If, for example, we're getting
data from a third party, such as a server or an API, we can eliminate bugs and errors by making sure our
data type is correct. For this reason, you
may have heard of tools such as TypeScript, which enforces us to
declare the type of data which you want
to use upfront, which can therefore eliminate
any errors in our code. This is how things work
with the plus operator, but the other operators
can also give us an expected results too
after coercion has applied. We can also see this
coercion in action with the greater than or the
less than operator. See this will change
the console log up with the value or the results of number one is greater
than number two. Let's see what happens.
We get the value of true. This may seem a little
strange because here inside the console log, we're still comparing a
string with a number. But in this case,
JavaScript is comparing them as though they
were both numbers. This is crazy behavior
for people who are used to other
programming languages, which is strongly typed. Meaning the data
is constrained to a certain type and
not converted. Although this coercion
happens behind the scenes, sometimes the examples
which we'll see have some pretty sensible or
predictable behavior. But often we do see some
strange results just like this. We can also see some
strange results when it comes to
incrementing too. See this, instead of having
a constant for our string, what we're going to do is
change this to be let. Therefore, we can update
this value of number one. Let's do this just below. We'll access our number
one variable then use plus plus to increment
this by the value of one. Console log the value of our variable and let's see what
happens inside the console. Refresh and we see
the value of eight. This may seem strange
because we know that number one is initially
set to be a string. Technically we
shouldn't be able to increase this by
the value of one, like we would do with a number. What happens behind the
scenes with coercion is number one is converted
to a number therefore, we can use the incrementor. I think you'd see the value
of eight in the console. As another example, imagine
this was also an array. If we surrounded this inside the square brackets
containing our string inside, what do you think would
happen now in the console? We still incrementing
this value. Lets say this and see what
happens inside of here. Refresh. Again, this
makes no sense. We still get the value of eight, but this is the
world of JavaScript. What about if we
commented out this plus, plus and directly added
a value to this array. Let's say plus 2, save, refresh, and we see
the value of 72. Again, this may seem
like crazy behavior, but what's happened
behind the scenes, as you may have guessed, is this has been converted to a string. If you wanted to prove
this was a string, or if we wanted to double-check, we could also use typeof
inside of the console log. I'll type of juice
before our number one, save this and this will then output the datatype
which is a string. Also here is something
else really strange too. This is a string as we've
just seen but what do you think would happen if we
re-introduce the increments? Well, let's uncomment this out, save and refresh, and we're
now back to a number. What about if we also remove the typeof and we can see
what happens when we add together the seven and
the two and then also use the increment.
Let's save this. This now gives us the result of the numerical value of 73. Meaning that what happens originally for number one is our was 7 and 2 get added together
to create a string of 72, just like we've seen earlier. This is still a string, but when it gets down to the next line, as we also seen earlier
when we use the plus plus, it then adds the
value of 1 giving us the value of 73
inside the console. In addition to all
of this craziness, the equality operator
also introduces a whole new world of things
to watch out for two. For example, in our console log, we can check if 1 is equal
to true. This is true. But what about if we
convert this to be a different number such as 11? This now gives us
the value of false. Just to recap, the value
of one was equal to true, but the value of 11
was equal to false. Let's try one more
number such as two, refresh and this is also
the value of false. But this is another
quirk of JavaScript, but just before we explain, I just want to add a few
comments at the bottom. So true is number 1 and
0 is equal to false. To understand this better, we need to understand
that when using the double equals,
just like this, this is the loose
equality meaning we're not checking for any datatypes
unlikely triple equals, which we've seen before. All we're doing is
checking if two values are equal regardless
of the datatype. Since we are comparing a number here with a Boolean
on the right, we're not checking it
through equal types. JavaScript will convert
using coercion and in this case it converts the
Boolean to be a number. Just as we wrote before, the number one is
equal to true and JavaScript will use the number
zero to be equal to false. We can test this in
the console log. We can check if the value of one is equal to false,
which is not true. It should give us the value
a false inside the console. However, if we change it
to be the value of zero, zero is equal to false, just like we've
seen below and it should then result in true. That's a lot of
quirkiness to take in and it doesn't
end there either. JavaScript has so many of these things which you
have to watch out for. I don't expect you to remember
them all at this stage. But knowing that this behavior exists and give you
a good head start knowing where to look if you're encountering bugs
inside of your code.
12. Truthy & Falsey: In a lot of these examples in this section and JavaScript
coding in general, we check if a value
is true or false. If it's true, we
then run some code, and if it's false, we
do something else. But it's not just
a Boolean value of true and false,
which we can use, as we've seen in the
last video other values can also evaluate to
be true and false too. Such as zero
evaluates into false, and the number wants
to be equal to true. There are also many
more examples too, such as a string
of text is true, and an empty string is
the opposite of false. This is referred to
as truthy or falsey. Truthy is when a value
is evaluated to be true, such as our string of
texts being present, and falsey is when a
value evaluates to false, such as our empty string
or our number zero. Jump into our editor, and
we can take a look at some examples down inside
of our empty script. If statements will run for
not only a Boolean value of true but also any other
truthy value too. Let's say this by
first setting up an empty if-else statement
then inside of here, we're just going to place in
it too simple console logs. For the first section, we're going to evaluate
something to be true, we'll pass in the text of true V. In the L section,
will do the opposite. Adding the text of falsey. Of course, this won't run at
the moment because we don't have any condition
inside the if statement. But we'll start with
what we already know. Previously we looked at the
values of zero and one, where the value of zero
is equal to false. This would be
evaluated to falsey, however, the opposite is
true with the value of one. Also, we can test the string which you mentioned just before. We have a string with
some contents inside, such as the text of hey. This will also
evaluate to be truthy too since we have some
value inside the string. But if we were to remove this
and have an empty string, this would evaluate in JavaScript
to the value of falsey. The coercion we've
talked about is happening behind the scenes, and values such as our
numbers zero and one and also this string value here is being converted to have a
Boolean equivalent. We can determine if
things like these if statements are to run on not. Falsely values, as
you would expect, are generally empty
values such as zero, which we just looked at, and also these empty strings too. Let's take a look at some
more examples such as no. This is also falsey. Undefined this should
also be falsey too. Generally, anything which
doesn't have a present value, so the word false. As you'd expect, this would
also evaluate to falsey. Finally, note the
number, which is NaN. This is also falsey too. We can consider pretty much
everything else to be truthy, such as the strings which
we just looked at, arrays, numbers other than
zero, and in fact, any object type
such as a function, array, or an actual object
will result to be truthy. This is also true
regardless of if we use the constructor or a literal
type, just like this. We could use the constructor. We've looked at things
like new array, and new object in the
past. This will be truthy. Let's try a function
constructor which will also be truthy too, and finally the object. In the exact same
way if we want to use a constructor
like this and we use this literally like we have done more commonly
in these videos, such as creating an array
with different values inside. This would be truthy just
like the constructor, along with placing in an
object in a literal font too. This coercion, combined with
understanding how values are converted to be
truthy or falsey, is a good thing to
understand inside of JavaScript since
it can really help you out to both
avoid problems in the future and also help
with debugging issues too.
13. Optional Chaining: This video is going to focus on something called
optional chaining, which was introduced in
JavaScript in ES2020. As we already know, we
need to have access to certain some inside
of an object, such as our name and
also our role of admin. Also as we know, we can go
even deeper by accessing objects nested inside
of an object too. What happens when properties inside of this chain
are not there? Look at some examples of
chaining in the events section, where we access
the event object. We then went deeper into
properties such as the target, the parent node, the children, and then into the
inner text value. If at any point in this chain
a property does not exist, we would then get an error. This is not a bad thing though, as we should get errors
if we do something wrong. But what about if
the property is only sometimes there
and sometimes not? An example of this
is what we've been using already inside
of the script. It will have the current user
which is set to a logged in user object and we have all the information
which we need, such as the name and the role. Therefore, when we go down
to the if statements and check if the user's
role is equal to admin. We know this should work
without any errors, but with users though we don't always have them
to be logged in. The current user is not always set to be an
object like this. For example, if the
user is not logged in, in place of this user object we may see the value of null. Now, if we try to run
the if statement, we don't have access
to this.role property. Therefore, let's go into the console and
see what happens. Inside the console we see
this red error message, which tells us there's a
problem with reading our role. This happens because the
current user is no longer an object which contains
the role property, therefore causing an error. But we still need a way to keep this role active inside
the if statement. But after the user
has logged in. This is where optional
chaining comes into play. What we can do is we can
insert a question mark to declare the property may
not always be there. We add this just before.role. Now if we save this and refresh instead of the
error inside the console, since it's now
evaluates to false, the else section will now
run inside the console. What happens inside of here is we get to the if statements. JavaScript will then
read the current user, which is the value of null. Therefore it knows not to go any further with the
rest of our chain. It now skips the
error and instead it returns back a
value of undefined, which we can check inside
of the console log. Currently we know
the else section is running because we've
seen the value of false. But instead what we
can do is we can access the current user, a question mark since this
is not always going to be there at the
optional chaining. Then we can add on the
value of the role. If we save this and refresh, we can now confirm we get
back the value of undefined. This is really useful
if we know upfront a certain object property may
or may not always be there. It's common for
objects like this to grow over time and we don't always know how our app
may develop in the future. We may need to add
extra features or collect more information. This optional chaining
can avoid any errors. For example, in the
future we may need to add more information about the
user's sign up source. We could add a nested
object inside, just like this, we will return
back to the user object. Let's reinstate the
name and the role. Then a second nested object inside which I'm going to
call the sign up data, this is going to be a nested object inside. We
will place in the date. But now an empty string is fine. It doesn't really matter and confirmed to be equal to true. Then even further down the line as our app developed even more, we may need to go even
deeper into this object. For example, we may want to
collect further details about the user's sign up source
inside of this object. We may also add the source, which is also an object where we saw the URL of
the sign up source. Again, this is just
an example so we can add anything inside of the string on the browser
which the user came from. Now we need to longer chains to access this nested information. If we just remove these
if else statements, and we'll simplify this
with a console log. We need to first access
the user objects, which was current user. The object inside which
was sign up data, so.signupdata, For example, if we wanted to
access the browser, we'd also need to jump into
the source just before this. The source object and
then the browser, refresh and this should now
be the value of Chrome. But remember in this example up, all of this was added to the
object at a later stage. Some of the earlier sign
up users won't have the sign up data associated
with their objects. What we can do, we can simulate this by commenting
this section out, which will then cause an error, just like we've seen before. Again, optional chaining
can help us out with this by allowing our code to fail silently rather than displaying an error
inside the console. Inside the sign up
data would no longer have access to the
source or the browser. We can add the optional
chaining inside here, refresh and now we see
the results of undefined. Overall errors are good to let us know when we've
done something wrong. But in cases like this one, we know we have a property which may or may not be there, optional chaining can really
help us out by failing silently and therefore allowing us to handle the
errors ourselves.
14. Creating & Modifying New Objects: Pretty much anything
we can think of has certain properties can be a good use case for an
object in JavaScript. For example, a person can be an object and the properties
could be the name, age, height, and
any other piece of information which we want
to give to a person. A computer could
be an object too with properties
such as the brand, the model, the CPU, the year of manufacture,
and also the memory. When we think of
objects like this, the use cases become huge. As with arrays, there
are different ways to construct an object, and the style we've looked at so far is called the
object literal. This is used to
create and define a new object with
the curly braces, which includes some properties, just like we have here. Over to the start files. Jump into this lesson's file, which is the object constructor, and open this up
inside the browser. As previously mentioned
with the slides, we have two different ways
we can create an object. We have the literal approach, just like we've used previously, and we also have an approach
called the constructor. The constructor is nothing new. We've looked at this
previously with arrays. Typically, we've created arrays using a literal approach, such as a pizza array, and set up our properties inside of these square brackets. As well as this
literal approach, we can also create an array
using the constructor. For example, if we wanted
an array of ingredients, we can set this up using the new keyword
followed by array. This is a literal approach
and this is how we can create an empty array with
the constructor. We can then access
our empty array and add new values with methods such as push to add
any new value to this array. In the exact same way as
our arrays just here, we can also do the same
for other objects. What I'm going to do
is to comment out this literal approach and recreate this using the
object constructor. First of all, we'll
create a new variable called user to mimic the above objects and set
this equal to a new object. This new object is going to be an object wrapper
which is empty, and then we can
go ahead and push new properties to this object. We do this by accessing
our variable. Then we can set the name of the property directly
to our object. First, It's going to be the
key, just like we have here. Then we assign this
to a certain value. This is equal to a
string of Chris. Then the second one is for
the last name, also a string. The third one was
the occupation. Next, we have the
logged-in Boolean of true for user.logged.in. This is a Boolean so we
don't need the quotations. Then finally, we can also assign an array to all foods property. I'm just going to copy this
array from just above. We can test this is
now working by doing a console log for
the value of user, and then jump into the developer
tools into the console. There's our object with all of our properties nested inside. We can also access individual properties too
using a dot notation. This works exactly like we did
with the literal approach. We can use user.first. This will print out our first
name inside the console. As well as this dot notation, just like we've used previously, we can also access
our properties with the bracket notation too. What we need to do is to surround our property name in these square brackets,
remove the dot. This also needs to be a string. Both of these give
exactly the same result. If we wanted to, we could
also directly update one of our properties
too, so user.first. We can then reassign this or update this to
be a new value. Then we can print this
out to the console. This will give us
our updated value. As a side note, if
we accidentally have more than one property
which is a duplicate, just like here where
we've got the first name twice in our code, since ES 2015, the last occurrence will be used rather than
throwing an error. As well as this, we can
also delete any one of these properties using the
JavaScript delete operator. What we need to do
is to add delete, which points our first
name, save this, and refresh, and
we'll just print out the full user object. Open this up, and
this will now remove the first name from
our use object. These is two different
ways to create an object in JavaScript. Personally, I prefer the literal approach
which we had at the very top since to me it seems more
clean and simple to use. But this is completely down
to your personal preference. In upcoming videos, we'll
cover how to set up a template-like function for
creating multiple objects.
15. Object Constructor Function: Great. We're now aware of two different ways of creating objects
inside of JavaScript. If you jump into
this lesson's file, which is object
constructor functions, we see we just have an empty
script inside of here. The two different ways
which we've created objects is to create a new
variable just like this, and then we can
add our properties directly inside of
the curly braces. Alternatively, we can
also use new object, which is the constructor
approach and this will give us an empty object at
our properties too. Both of these
approaches work fine, but they're also limited to only creating a single object. It would be more helpful
if we could have a object template so we can create multiple objects
based off this, each showing the same
properties and methods. We can also do this with
the constructor function. What we'll do is
we'll remove this and create a new
constructor function. It's also good practice to name these constructor functions
with a capital letter. We use in our user example, it's an uppercase U, and then create the rest
of our function. The purpose of this
constructor function for our user is to create multiple users based
off this template. Inside of our function,
we're also going to pass in some values which we're going
to need inside of here. The first one, we'll
keep this pretty simple, we just say first, last
name, and occupation. We'll come back to this
function in just a moment. But before we created
a new object, just like this, so we used the new keyword and then
the object function. But now instead of creating
a new empty object, we want to create a new
instance of our user. Rather than new object, we'll
say new User capital U, where we're going to pass
in the actual values which you want to use
for our function. We need to pass in the
first name, the last, and the occupation and
these are going to be the actual three values
we need for our user. We'll say Chris, the last name, and finally the occupation. We can also duplicate this
as many times as I want to, because as we mentioned, the whole purpose of creating
this constructor function is to act as a
template to create as many objects as we want to. We create our second one,
has a different name, and also eight different
occupation too. With both of these new users, we can also store this
inside of constants or variables so we can
access them later on. So say const chris
equal to our one, and then the second
one is equal to homer. Great. Now what we're
going to do is to log the value of any
one of these new users. Placing a console log, the value of homer, and
then jump into the console. As you can see, we've
got a user object. But if we open this
up, we don't have any properties inside of here. All we have is an
empty user object. This can be expected because our constructor
function which we created earlier is empty. We don't have any code
inside of the curly braces. We receive in the values
inside the function but we're not actually doing anything with these just yet. To do this, we need
to set something to be equal to these three values. We need to set something
to be equal to our first, some things to be
equal to our last, and something to be
equal to our occupation. But what do we do to turn these into our object properties? Well, to set a property, we need to make use
of the this keyword. To understand the this
keyword a little bit better, I want to quickly
take you back to an earlier file in
this project folder. If we jump back into number
three, which is functions, and then number five, which
is a function or a method, jump into this index
page just here. Inside of here, you may
remember we created an object called check recipes. Check recipes had
some properties such as the current
number of recipes, the maximum recipes, and also a method
called recipes left, which deducted the
current number of recipes from the maximum. Remember a method is just a function which is
located on this object. Inside of this method,
we made use of the, this keyword to access other
properties on this object. We access the max recipes, which is on this object and
also the current recipes too. The this keyword can be a complex thing to
understand in JavaScript, but in these circumstances, it will simply point to the
object which owns here. Meaning we can access any of the other properties
inside of this object. With this in mind, back
to our current file, we can now add all properties in the exact same way by using the, this keyword followed
by the property name. For the first will say this.firstName and also the
same for the others too, this.lastName, and
finally, this.occupation. This will now construct
our two user objects with the properties
which we pass inside. Save this and with
our console log still in place, refresh. Our Homer user is now
constructed correctly and we can also duplicate
this for our first user to. This now gives us
two unique objects, which are both based
off the same template. If we need to add extra
properties and methods, we have some options too. We can add them directly to
one of our objects like this. Just like we looked on
the previous video, we can access our
variable such as homer. We can say lives, and set
this equal to our value. We can also add methods
to our objects too. We can access our object, which is homer and
then we can give this a property name
which is going to be full name and set this
equal to a function. The responsibility
of this function is going to be to
return a new string, which is the first name
added to the second name, so return our string, which is homer.firstName, add an empty space in-between and then add onto the
end homer.lastName. Let's give this a
try. First of all, we'll try the lives property. Add this to the console, refresh and we get the
value of Springfield. Then next we can try our
method which was full name. Refresh the browser. Whoops, we've got a value of undefined so let's
check this out. We've got homer.firstName,
that's fine. Just a spelling mistake up at the very top of the air
so we'll change this. Now we see this is
Homer Simpson this so this is working
completely fine. But these are only added
to our single objects. These are only added
tall Homer variable. If we did try to
access in our Chris variable and try
this in the console, we see an error inside of here. This approach is
only useful if you want to change one
specific object. If we want to make these apply to all of the created objects, we do need to place these on the constructor
function at the top. So first of all,
we need to pass in the property of lives to our function and then we can add these to
our two objects below. Chris, value of UK and Homer, the value of Springfield. We also need to modify
our function body. We'll duplicate this and
we'll say this.lives is equal to the value of
lives which you pass in. We also need to pass
in the method too. The method will
always be the same, it's just using the existing
first and the last name. I'm going to just cut and
paste this into our function. Cut this, paste this
into our function. This time we're going
to remove homer, replace homer with
the, this keyword. Also the same inside of
our function body too. Remember, just like
the previous example in the earlier video, this keyword will point to any other property on
this user function. Finally, we can also
remove homer.lives. We no longer need
this, so now we can save this and refresh. Now the full name method works
for both of our objects.
16. Object Prototypes: If you did not quite
understand the role of the prototype in
the early videos, hopefully now seeing
it in action with our own objects may help
to make some things click. In the starter project, we begin with the object
prototype section with the same example
from the previous video. We have a constructor
function to create templates or blueprints. This means we can
create multiple objects with the same properties
and methods available. We then looked at how to
add properties and methods, both for a single
objects and also to the function so they apply
to all new objects created. Along with adding to the
constructor function, we can also add directly
to the prototype too. But before we do
this, let's first refresh what we know
about the prototype. Down to the bottom, we're doing a console log with
the value of homer, which has created a new user
object from our constructor. If we open this up inside
the browser and jump into the Developer Tools
into the Console, and let's take a look at
what we see inside of here. Refresh, and we see our user. Let's open this up. It
contains our properties. We've got the first
name, the last name, and all of the values which
you see down at the bottom. Then down at the bottom
we have this prototype, which is a link to the
prototype chain. Open this up. Inside, we can see our own constructor,
which is our user. Also alongside this, a
second prototype objects. The first protocol, which is
the one up at the top here, this points to our own
prototype additions, which we'll look at soon. Then the second one
which we just opened up, this has now lots of
things inside of here, which we didn't add ourselves. We have things like
valueOf, toString. These are not things which
we created ourselves. Remember, from earlier, JavaScript objects
inherit properties and methods from parent objects. At the very top of this
inheritance chain is the object. Let's now log this to the
console for reference. Just with Homer I'll do
a second console log with the value of object. Now let's save this and
refresh the browser, leaving us with the
main object type alongside our own home object. This first object value
is an empty object, which you can see if
you open this up. It's empty in terms of having no properties of values
inside like we have here. But the purpose of
this top level object, even though it's empty, is to contain the bare minimum
properties and methods that pass down to other objects through
the prototype chain. We can see this if
we open this up. This contains all of these properties and
methods which we can now have access to through
our own created objects. If we now open up
our own home object, go down to the prototype. Then the second
prototype inside here, you can see this has inherited the same properties and methods from our
top level objects. This now means these
are now available to use in our own custom objects. As we looked at earlier, this is why things
like custom arrays have methods available, such as for each push and pop. We didn't actually create
these methods ourselves. But instead, they are inherited
from the prototype chain. All the rays can
make use of them. We shouldn't add our own
properties and methods to objects which we've
not created ourselves, but we can add them to our
own custom constructor, such as this user. We can do this by accessing the prototype property
on this user. Just below this. Let's
make some space. Access our user constructor. Then the prototype. We can set a new property
on here, so any value. This can be other data
types such as strings, numbers, or even methods. We can also remove
the first object, leaving our second
homer object in place. Refresh, open this up, jump into the prototype. Now, I'm going to open up
this prototype object. We also see the custom property,
which we have just set. We see cool is not placed on the original object alongside the first name, for example. But if we try to access it, cool, then be looked up
on the prototype chain. If it was not on our prototype
chain, which you see here, it would look even further up the inheritance chain.
We can test this out. Jump into the console log. Now, homer.cool. Remember,.cool is not available on our
original constructor. It's then going to look down the prototype chain, refresh. We get the value of true. The same goes for methods too. We can also add different
methods to the prototype. Rather than having this method available on our constructor, what I'm going to do is to copy this and comment this out. Paste this outside of our user. This time, rather than accessing
the object through this, we're going to access
our user.prototype , just like we did before. This time, full name is going to be equal to our function. Let's test this out down
in our console log. The name this time was fullName. With this being the
method, we also need to access this with the brackets. This should now
return our firstName, added it to our lastName. Good. If you also
want to check this is on the prototype alongside cool. We can remove fullName. Log to the console,
the value of Homer. Open this up, jump
into the prototype, and our two new editions
are inside of here. To begin the prototype
may seem complex, but it's just a way to inherit properties and methods
from a parents object, even from a parent which
were created like our user, or from the top level object
which JavaScript provides. To recap, the prototype is
a property on an object. It will make available to be
inherited by other objects. An example of this
was our fullName and our cool additions. Both of these were
added to our prototype, meaning these have now
been made available for other objects to inherit, such as our Homer user
down at the bottom.
17. Inheriting Object Properties: We've talked a bit so
far about how we have this main parent
JavaScript object, which has a prototype, and how one would create
new ones they automatically inherit certain things
through the prototype chain. But what if we
wanted to also allow our own objects to
be inherited too? In a start files we have
a similar user example from the previous video. We have a user object, and we may begin to realize
that this user object has some limitations
for our particular use. Here we are creating
real people such as me and also just below
a fictional character. But if we think about this, real and fictional people may
need different properties. We may, for example,
want to add the name of the show which the fictional
character was from. But this would not
apply to a real person. This now makes it difficult to expand this object much further. What we can do though, is use
this user object as a base, including only the bare
minimum properties which apply to both the real
and the fictional user. Then we create two more objects, which will both inherit
from this original user. We still have access
to all the things like the names and
the occupations. But then it will also have specific properties which
we need for each use case. To do this, we have an
object method called create. Just before we add this
to our current example, let's take a look at
how we can do this with a regular standalone object. First, let's add any regular
object down at the bottom. Remove our console log for now, create a new object
called product1. Open up the curly braces and
we'll add our properties. The title, again, this
is pretty generic, so an amazing blue shirt. Also the description. Simply all blue shirt. As a standalone object is a generic object which could apply to
multiple blue shirts. The title and also
the description will be fitting for
other blue shirts. We could also change
some details such as the brand or size
for other products. We could then use this
object.create method we mentioned before to create a second product based on this, install this inside
of a variable called product2 and set this
equal to object.create. Inside of object.create, we pass in our product1, meaning it will create
a new product called product2 based off our
original product1. Let's log this to this console, product2, and see what
happens inside of here. Refresh. Let's just update
this link inside the browser. Initially, we see
an empty object. We don't have any properties or methods associated with this. But if we go ahead and open up the prototype which is attached, we have access to our title and also our description which is inherited from our product1. This is how the
create method works. It creates a new object and uses the existing object we
pass in as the prototype. Again, notice how we also
have a second prototype too. We have our own first, which is the description
and then title. Then further up the
chain we have all of the properties and methods
which we've seen earlier, which is inherited
from the top of the chain from the object. As we've already learned, even though our own
object is empty, we can still access these inherited properties
from product1 by their name. product2, remember this is completely empty as we've
just seen in the console. We can access the inherited
values such as title. We can also add our
own properties and methods too, as
you would expect. Just underneath our product2, we can access this by
the name and then set new properties such as
the size, such as small. Log this to the console, which then updates our object. Now we can remove all
this example and we can use this knowledge
which we've just learned. We can now try to apply the
same example to our user. But the key difference
here is we have a constructor function rather
than an actual object. If we were to do
the same as before, let's create a
variable called copy, which is set to object.create. Then if we try to make
a copy of our user, let's see what happens
inside the console. Save and refresh. The copy is a copy
of the function, which is not what we want. What we're looking for
is a way to create more constructive
functions which all inherit the
properties of this user. Let's start with the character. Just below our user, create our new object constructor
called character. Remember the purpose of
this function is to inherit all of the base properties
from our user objects. We're also going to add some additional properties which only apply to our character. This extra information
which we're going to pass in is the show which
the character is from. Then just like above,
we'll access this.show, setting this equal to
the value which is passed into this constructor. Now, what we do is to create
a new character object with the show property and also inherit all of these
properties too. But this, we need to go into
our character and first access our user
constructor function, which we can then access
a call function on. This call method is available on a function's prototype and it allows for a function
belonging to an object called inside
of a different object. Meaning, we can now call a user function from inside
our character function. This call method is not
exclusive to this use case. It can be used anytime
I want to access a function or a method located
on a different object. This user function also takes
in these four parameters. We can copy these and also
add this to our character. Now, remember Homer
is a character, so rather than basing
this off the new user, we're going to base this
off the new character. As the fourth
arguments I'll show, just after Springfield, we
can pass in our last value, which is the Simpsons. These five values now match the five character
values passed to our constructor.
Let's try this out. We can remove our
copy from before, and instead we'll log
the value of Homer. This now shows that Homer
is a character object. It has the show property with
the value of the Simpsons. We know homer.show
should now also work. But what about the other
inherited properties? We could see before the
Homer object it would only had access to the show
property on the top level. We didn't have
anything else such as the firstName and lastName, the occupation or lives. Well, let's try this out
and see what happens. First, try the occupation. Refresh, and we get
back the value of undefined. Let's try one more. homer.lives and this
is also undefined too. The inherited properties
don't seem to work here. This is because we're
missing some details when calling our user function
inside of our character. First of all, we need
to copy over all of these parameters
which are passed in and also add this
to our call method. But in addition to this, we also need to pass
in this keyword. We mentioned earlier
that this keyword can be complex thing
to understand. We'll have more on this later. But this is basically
saying that when running our function, we can access the
values using this. Just as we were above. Scrolling down, we're still
trying to log homer.lives. Let's refresh this and we now get the value
of Springfield. We can try one more,
the firstName. This is all working correctly. Just as a recap, because this
can be pretty confusing, we're creating a
new Homer object based off our character. This character
constructor function only has one property of its own, which is the show which
the character belongs to. But it's also inheriting all of the properties and methods
from our user objects, which we are passing
in just here. In fact, we also don't need
to add this shows since it belongs on this
particular function. With all of this complexity, if we want to check which one of our constructors created
a particular object, such as Homer, we can use
something called instanceof. We can check this
inside the console log. We can check if the homer object is an
instanceof character. Should be the value
of true since we're basis of our new character. But if we were to
pass in our user, this one will be false. This is how JavaScript
does things. It has objects right from the very beginning that
we can inherit it from. As a newcomer, we
don't even know this is happening
behind the scenes. But if we were to dig a
little bit deeper like this, we can begin to
understand that this is so each new object, objects also referring
to other types such as arrays and functions
and have a set of helpful properties
and methods which we can use each time
we create our own objects. As we just discussed, we
can also take advantage of this prototype inheritance by
our own objects if needed.
18. Copying Object Properties: In the past videos, we've
gone pretty deep into objects with things like
object constructors, and copy and prototypes. But sometimes we simply
just want to copy the properties from one
object over to another. There are a couple of
different ways to do this. First of all, we have
the base character with information which could apply to all new Simpsons
characters we create. Pretty generic information, and then below we also
have a homer object with some properties which only
apply to this one character. For homer and also any other
characters which we create, we also need to merge in all of the properties from the
base character too. A straightforward way to do
this is just to reference this base character inside
of the homer object. We got add this as a property, has it in the base character, and test this over
in the console. We already have a console
log for the value of homer. If we open this up, we have the four original properties and we also see our
base character. This works completely fine, but it does create a
base character object which we need to open
up and dive into. Our base character is nested one level deeper than all of
our other properties. But it would be better
if we could grab all of these base character
properties and effectively put them alongside
what we already have. One way of doing this is
by using objects spread, which we looked at earlier, which was the three dots. Passing the three dots before
our base character object. Now we don't see the
base character object which we need to dive into. Instead, we see all of the base character properties
alongside our homer ones. We could also use this
technique to spreading as many different
objects as we wanted to. For example, if we had a homer Simpson character with superpowers for one
particular episode, we could do something like this. We could create a new
object called a superHomer. SuperHomer would
also need to inherit the base character and also all of the existing
information from homer. We can also remove this too. We can use spreads pass
in both of these objects. The base character and also the existing
homer information. In addition to this,
we can also pass in our own properties, which is specific to
this single object. For example, we could set
powers to be equal to true, and this should now display one big object
inside the browser. Let's just change over our
console log to be superHomer. Refresh and now we have nine different properties
on this object. We have the fall from
the base character, the forefront of Homer object, and also the powers set to true. We could remove or
comment out this object, and we'll now take a look
at another way to copy over the object properties
to a new object. This is done with an object
method called assign. Access our main object,
the assign method. This is going to take
in it two things. First, the target object
which you want to copy to. We'll copy it to
our homer object, and the second one is the
object which you want to copy. Using our original
example to move all the properties from our
base character into homer. Pass this in as
the second value. In the console log to be homer. Jump into the console. This now merges all
the properties from base character into
our homer object. Effectively works just like the spread operator which
we looked up before. Also if we needed to, we can
store this new object into a variable such as mergedHomer. This should also work
exactly the same. This assigned technique and
also the previous ones, are really useful and
something which you may often use in JavaScript. It has lots of use cases such as if we had a user and an order, we may want to attach
a user object to our order before saving
to the database, so we know who actually
placed the order. You will also probably find many use cases of your own too.
19. CSS Style Objects: In the DOM section, we created
our own HTML elements. Then we looked at how to add CSS styling to these
elements using JavaScript. In the Style's file we have an example of this
down at the bottom, a simple header section with
a title no meat burgers. Then below this inside
of our script we have multiple style
properties applied. This works fine as we can
see inside the browser, but it can be a pretty
long way of doing things. It's not re-usable on
other elements either. A solution to this is to
create a style object containing all of
the CSS properties and values which we need. Let's go down to the bottom
and we'll comment out all of these existing
styles and we'll recreate these inside
of a style object. Store this inside of a
variable called styles. Say this equal to an object, and we'll effectively replicate
these inside of here. First of all, the display is
equal to the value of flex. Since this is an object, we need to separate
this with a comma and the next one is justifyContent. Since this is JavaScript, we also need to make
this camel case, justifyContent and
every word after the first one needs to begin
with a capital letter. The value, this can be the same, this can be space between. Next, we have a padding value. Again as a string,
zero top and bottom, and 10 pixels on
the left and right. Background. What
do we have here? We have an RGB value. Let's copy this over.
Finally, the color. Let's grab the value
which we already have , paste this in. Let's go over to the
browser and refresh. We don't have any
styling applied. Now we need a way
to actually apply the style object to
our header element. Just like the last video
we can use object.assign. This will copy all of our
style object properties over to this header element. Down at the bottom of the
script object.assign. We want to apply
these to the header. The object properties
which you want to apply is our styles. But just as it is like this, it doesn't work if we
refresh the browser. The reason why is just
like we did originally, instead of applying these
to the header element, we need to apply these
to header.style, so at.style and refresh and it should now all take
effect in the browser. At the moment you may be a
little bit confused as to why an object method such as assign is working on an
element such as header. Well this is because
our elements, like many things in JavaScript are also classed as objects. We can see this
with a console log. We can use the typeof operator,
and the value of header. Then let's see what happens
inside the console. Refresh and you can
see that the header, even though this is an element, is a type of an object. When we create new
elements, we're actually creating element objects and this is how we can
have access to properties, methods, and events. We've already used
properties such as accessing the attributes, class list, and inner
HTML to name a few. Methods which we have used include queryselector
and addEventListener. These are all available
on this element object. But why create a style object
instead of regular CSS? Well, CSS is probably
easy for many use cases, but this way has
its own uses too. The main one for me
is the fact that it is controlled with JavaScript. We can change
values dynamically. If we had a game, for example, we could change the
background to be red if the game was over. We can make a count down flush faster as it's getting
closer to the end and so many more great use cases by updating any one of these
values dynamically.
20. Looping With Objects: Objects can have
many values as we know and just like with arrays, looping is a convenient way to repeat something
for each property. There is a couple of
different ways we can use to loop over objects, and first, we take a
look at the for-in loop. Inside of this lesson's file, we have a constructor
function up at the top, which we've seen before
to create a new user. Notice the prototype
additions are commented out and
we'll see why soon. For-in loop should
look pretty familiar. We've already looked at this
in the loop in section, but I want to show you
something else related to it. As a refresher, this is how
it looks inside of our code. It begins with the for keyword, and for this example,
we're going to loop over our homer object. We need to create a
variable for each one of the properties
inside of here, so the first name,
the last name, the occupation, and lives. This inside of a variable or a constant called property
inside of our homer object. Now we'll just open
up the curly braces and then inside here, we can do anything we want
to with this property. But now we'll do a console log, open up the back ticks so we can insert our property variable, which is our property name, such as first name, add a colon, and
afterwards we could also access the value
of the property. Again, we'll insert
this as a variable so we need to access
our full homer object, and inside the square brackets, we'll pass in the property we
want to grab the value of. Save this, refresh, and we see each one of
these four properties inside the console. We see the actual property
names such as first name, and then we use this to select the property value from the
homer object, such as homer. We can then use these values to construct elements to
now add it to the DOM. First, an unordered
list is required, which we can use as a wrapper
for all of these values, so jump up to our body
section outside the script, has an unordered list, and the first step is to grab a reference to our elements. Const ul is equal to
document.querySelector, pass in our unordered list. This now gives us two things. We have a loop, so
we're looping over all of the properties
inside of our object, and now this gives us an
element to attach this to. With this being an
unordered list, we need to create
a new list item for each one of these values. Const li for our list item, we'll create this with
document.createElement(). An element is in li. Remember when creating
new elements, this is generally a
three-stage process. We create the elements, we create the contents, such as the text node, and then we merge
these together. The second part of this is for the text which goes inside
of our list element. We do this with
document.createTextNode(), replicate what we've
seen inside the console. All we need to do is to copy the contents from
inside of here, and paste this inside
of our method. Remove the console log,
merge these together by first accessing our elements and use the method
called appendChild. We will pass in our text. This has created a new
standalone elements or a standalone list item, and then for each
loop we need to merge this or insert this into
our unordered list. Just like we did
above, we'll grab our unordered list and
use the appendChild. Passing it the list item we just created. Save and refresh. There we go and this is
a really good way to structure our objects to
show inside the browser. But back to this prototype, which you mentioned before, which is currently
commented out. If we uncomment this out, let's save this and now
again, refresh the browser. We also now see these two prototype values inside of here. This is something we need
to watch out for and if we don't want to loop
over these prototypes, which is often the case, we can eliminate them using an object method called
hasOwnProperty(), which we can use
inside of the loop. Let's go down to
our for-in loop, and at the very top,
add an if statement. We will pass in
homer.hasOwnProperty(), passing in our
property variable. What we're doing here
is we're accessing our full homer object and then checking each
property one-by-one. We are checking if the
particular property belongs to this homer object, or if it is inherited
via the prototype. If this is true, we want
to run our code below. If not, it will be a prototype value and
therefore ignored. We can now cut this out of place and add this inside
of our if statements. Refresh, and this is a way to ignore our inherited
prototype values. Another way of looping
over objects is to first convert them to be arrays. Object has some methods available which you
can use to do this, and depending on if you want to access the object's property, the value of both
of them as a pair. Let's begin with a
method first called entries at the very bottom, place in a console log
for objects.entries(), and our object value of homer. Test this out, jump
into the console, and it still returns
back in array. Not only is this
returning back in array, each one of the properties
is also an array too. It contains the property name and also the value
as you can see here. This method does not include the prototype values like
it does with for in. If we were using
this, we could ignore the if statements that
we have just here. To give this a try, and
keep the same example, up the for in example, and then comment this out. Paste this in just below. I must mention, we don't need this if statement
since we don't need to eliminate any one of the
inherited prototypes. Remove the wrapper, leaving
these four lines inside. This time rather than it
looping over our homer object, we're going to now make
use of object.entries. We're going to move this,
and just like we did inside the console log
replacing objects, data entries with
the value of homer. Save and refresh.
Inside the browser, we see the values of undefined. This may not be obvious
at first to why this is, but this is because of the
type of loop we're using. We currently using
a for in loop, which is used on objects. But now we're converting
homer to be an array. This now means we need to make a small change and
instead use a for loop, so change in to be of, and remember now this property, instead of returning a single
property as it was before, is now going to point
to an array which contains two values such that
our first name and homer. What we can do instead of this is to D structure
using the array, which will give us the
key and also the value. The key in this case is
equal to first name, and the value is going to
be equal to homer for each one of our items. Pass this in. First of all, the key,
and then also pass in our value. Save this. Reload. This again
works as expected. This is a really
good way of looping, which doesn't involve
the prototype. If we want to, we can
also access the keys, all the values individually
too. The way to do this. As an example in
our console log, if we just want to
access the keys such as first name
and last name, we can use an object
method called keys, where we pass in
our homer object, and there's our four
keys without the values. On the other hand,
if we just wanted to access the values
and not the keys, we can use object.values, and this will return this
back inside the console. This is also commonly used in if statements just like this. We could say if object.keys(), pass in our object, and access the length property
is greater than zero. We can then do something
inside of here. This checks if an object is not empty before running some code, and it just depends if you want to access either the key, or the value, or both.
21. Dynamic Objects: This video is going to convert creating more dynamic objects. By that, I mean both the key and value can
be changed using JavaScript. When we create new objects, just like we did with
this home object, we're using simple primitive
value such as strings, but our programs are not
always going to be this rigid. We may also need to insert
data which may change, such as a variable. Also, even with the
key names such as firstName and lastName
and occupation. This could all be dynamic too. I'm going to now show you
some ways to do this. First, the more
traditional ways, and then a way which was
introduced in ES2015. We begin by inserting
variables as values, and this is pretty simple to do. Let's first create a variable called firstName and set
this equal to homer. We can then reference
this variable inside of our property value when we
create our new homer user. Remember, since we're
now referring to a variable rather than a string, we need to remove the
surrounding quotes. Save this and refresh. This works just like before, but this time we are now
pointing to a variable. We already know we can add new
properties also like this. We can access our object, access the likes property, and set this equal to a string. Save and refresh, and this is also
added to our object. Currently, value of likes
is set to be a string. We may also want this
to be dynamic too. Let's try and set this as a variable rather than a string. Remove the quotations. I'm going to create
this as a variable just above, const likes, and insert our string inside the back ticks so we can insert our variable all
passing our firstName. In this case, it
will say homerlikes, followed by a particular value. I send firstName,
a text of likes, and now our likes inside of here will point to our variable, which is now shown
in the browser. It also takes into account
our firstName variable too, and places it in as
part of the string. If we had multiple likes, we may also want to number them. We can begin by creating
an initial value. We'll say let number be equal
to an initial value of one. Then append this number
value to our variable. As we would expect, we only
have the single number 1. If we were to duplicate this and change this to be a second
value such as Donuts, we could increment this number
by one using plus plus. This will be increased for
each one of our values. Remember that all of this
is constructed using our object constructor
function up on the top. We can also do all of this using the object literal approach. At the bottom, let's
create an object literal, and we'll call it homer2, and set this equal to a
literal object where we set our properties such as firstName or we can also make use of our
firstName variable too. Log this to the console. As you can see, our
variable can also be inserted using
this approach too. But this may start
to look a little bit confusing because here, we point to all
firstName variable, but also the property name is still pointing to this
firstName variable too. So why do we see this output as a string rather than
the value of homer? Well, for the key, we don't need to wrap this name in quotes. This will always be
displayed as a string. So how would we go about
making this property named dynamic if we can't use a
variable just like this? Well, one option would
just be to create an empty object without
any properties inside. Then we could add
properties just like we do above using the
square brackets or alternatively using
an ES2015 feature called computed property names. We could use the square brackets directly inside of our objects. So surround our firstName
property with the brackets, which now says that
the code inside of these brackets is not to
be treated as a string. Instead, it's evaluated as
a JavaScript expression, meaning if we now display
this inside the browser, instead, we now see
the value of homer, which is our variable. Even this full control
over the properties key, and also the properties
value using JavaScript. We could also pull
in our properties just like we did from above. We could access this
without the homer prefix , paste this in. The only difference is
rather than the equals, we need to change
this via colon. We can also add our
second one to of Donuts. Add a comma, place a colon. Let's try this in the
browser. Open this up. So this is now
inserted, but instead of the values of one and two, we see the values of
two and three since we already incremented
this just above, we can comment this one out. It's taking us back to
our original example. This is how we can use
computed property names with our objects to make both the key and also the value more dynamic
using JavaScript.
22. Primitive & Reference Types: We use variables a
lot in coding and JavaScript to store our data. But if we go a little deeper, there are some important
concepts to understand and that is the we values we
store fall into two groups. To better understand this, I want to first refresh what we already know about data types. We have primitive values, which are simple values, such as a string or a number
which has no methods. We also have object types too. These two groups directly relate to what we're
going to look at now and this is storing
primitive and reference types. A string variable
would be a primitive, and an object type, such as an array variable would be classed as
a reference type. Both of these types
impact the behavior of values when we pass them
around and compare them. Let's first jump into
our starter project and take a look at primitives. In the script for
this lesson's file, we'll create a new
variable called Dog and set this
equal to a string. Next, create a second
variable called newDog, and we'll set this equal to
our original dog variable. This one is effectively a
copy of our first variable. Then we're going to reassign
newDog to be something else. Remember, the way
to do this is to select our variable name, and set this equal
to any new value. The next thing to do is to do a quick test with a console log, beginning with our
first dog variable, and then a second console
log for our new dog. Let's see. Well, this froze
up inside the console. We see the value of poodle, which you would expect from
our first console log, and the second console
log of newDog. Even though this was originally assigned the variable of poodle, this has been updated to
be the text of Labrador. Nothing unexpected
here, even though we've copied a
variable originally, the new one is still
a separate value, completely independent
of the original. Basically, we can modify
the original dog, or the new dog and they
will not affect each other. This is the behavior
of primitives. The variable points to
the actual saved value. Storing object types
behave differently. Let's do an example
using an object which we can copy just
like we have done here. First of all, we'll
create our variable called laptop 1 and set
this equal to an object, which of course is
an object type. The properties or brands, and the data inside
of it doesn't matter. The model set any
value as a string, and then just below, we'll make a copy of this, just like we did
with our newDog. This one will be
called laptop 2, which is equal to laptop 1. In the same way we did at the very top with our primitives, we'll update or re-assign our laptop 2 then we'll
add a new property, such as the size. This time for the console logs, the first one is laptop 1. I will also see what
the value of laptop 2 is. Test this out. Refresh. We'll see both of these values are
exactly the same. This may seem really
strange because we have the size property on both laptop 1 and also laptop 2 even though we've only added this
to our second variable. Meaning that seems
to be a link between laptop one and laptop 2. When we created our
variables stored in a primitive just above
with a string, the variable points to the actual unique value
stored in memory, and these are all unique values. However, though, when
we create a variable containing an object type, the object is still
stored in memory. But these variables,
such as laptop 2, holds a reference to
that object's location rather than the actual value, hence the name reference type. Here we're creating our
original laptop one, and then each time we create
a copy such as laptop 2, it all points to the
same original object. Since all copies are
pointing to the same value, this is why when
modify any of them, such as here, the original
will also be updated too. Some other languages allow
us to change this behavior. But with JavaScript it's fixed. Just as a quick recap and maybe clarify if you are unsure. When we create a
variable to store in a primitive, such as a string, the variable points to an actual unique value stored in memory, meaning our Dog and
also our newDog, are completely unique
and independent values. However, though, when we
create a new object type based off an original object, the copied version will
hold a reference to the original object's
location in memory, hence the name reference type. This is something which
you probably don't care too much about
it until we maybe run into an issue where you change one object and they all
change unexpectedly, and you don't know what
is causing the issue. With this in mind, next, we'll cover how we can
compare two objects.
23. Comparing Objects: What we learned in
the previous video is that a primitive value is unique and stored by a value and an object type is
stored as a reference. This will now help us better understand the behavior we're about to see when
comparing two objects, it's that inside of our
starter files we have two similar objects with
the same properties. They both have the
brand and also the model and also
the same values too. We're going to use these
to compare quality. From a sensible guess, you would think that if we
compared both of these, that they will be
considered a true match. This would be a fair assumption
since both of these have the same brand and
also model too. Jumping into the console, if we do a comparison
with primitives, this is pretty simple. If 1 is equal to 1, this would return back
the value of true. This is simple because
primitives have their own unique value
stored in memory. Comparing values works
as you may expect. Objects though are
little less obvious. As you may expect, comparing the same object like
this results in true. Laptop 1, if we compare
this to itself, which is laptop 1,
this is also true. But if we change laptop 1
to be equal to laptop 2, even though these both have
the same brand and model, we get back a value of false. Even though these
two objects have the exact same contents, they are not considered equal. The reason is because
these are reference types. Remember, a reference type variable points to a
location in memory, not the actual value. Here we're not
actually comparing the contents of both
of these objects. Instead, we're comparing two
different memory locations. This is why the
comparison is false. I know this can seem
a little confusing, but this is just how
JavaScript works. Going back to what we looked
at in the previous video, what do you think will happen
if we copied an object? For example, if we
set the constant with laptop 3 and set this
equal to laptop 1. Well, let's test this out. We can check if laptop number
1 is equal to laptop 3. Remember, here we're making a copy and this results
in a value of true. Now, this one comes
back true because when we created laptop 3, we didn't copy the
contents of laptop 1. Instead, laptop 3
will now point to our original laptop 1
location in memory. Regardless of how all of these variables are
stored behind the scenes, we may still need
a way to compare the properties of two objects. We need a way to compare
laptop 1 with laptop 2, which is going to
result in true. One way to do this is to use a JSON method called stringify. We'll look more into JSON data. Stringify is a way
to convert an object into a string and
it looks like this. Parsing JSON, a method
called stringify, we're going to parse in
the value of laptop 1. If we test this
inside the console, we can see our object is
being converted to a string. Comparing a string
version of laptop 2 with a string
version of laptop 2 will make our comparison much easier. We'll do the same. We'll check if this is
equal to json.stringify. This time we'll parse in
the value of laptop 2. Jump into the console. This is equal to
true since both of our string values are
exactly the same. One of the issues though
with using this method is the properties must be in the exact same order
for this to work. If laptop 1 and the brand
is our second property, this would result in false. To fix this, we have a couple of different
ways to check this. The first one, which
is only really good for comparing
simple objects like this is we could create a
function called check equality, which is going to manually
check our two objects. When we call this, we're
parsing object 1 and object 2. Then we'll return back
the value of if object 1. The brand is equal to object 2. That is our first comparison. Afterwards also we want to check if the model
is also the same. The double ampersand, check if object1.model is
equal to object2.model. This is a long way round. It's a manual way of doing
things, but it would work. We can check this out by calling our check
equality function. Our two objects is
going to be laptop 1 and also laptop 2, these are the two which
you want to compare. To see what the return value is, we can parse this into
our console log, refresh. Object 1 one not defined, I would just need to make
sure these have a j, refresh, and this is
the value of true. Now it doesn't matter
which way around our properties are in
each one of the objects. We can still do a simple
or manual comparison of each one of these. Another option is making use of object methods to access
the keys and the values. We've already looked
at these in the looping with object video. Remember that we access
the object, a capital O. We can then go up the
keys such as model and brand or laptop 1, like this. There's
model and brand. Also, we can do the same
for object.values too. Using this approach,
we can modify our check equality function for all of the keys and values
and check if we have a match. This way also means that the order of the
properties is not important as it was with
the first stringify method. As you can see, object types
can be a complex thing. If you don't understand how
they work in JavaScript, it just takes a bit of
experience to get used to. But I don't expect you to remember all of this first-time. But just being aware of things like this will really
help you out in the future if you run into
any object related issues.
24. Section Introduction: Coming up, we'll
have a great project for you to work
through and this is going to give you
lots of practice with what we have learned so far. This is going to be our project which is named Speedy Chef. The whole idea is we're going to cook pizzas that come through via orders and try and get
as many completed as we can, so with the chef and
we can start the game, which is going to start the
service for the kitchen and then we can see our orders
coming in over on the right. When we want to start
working on an order, we simply click on one and it then pulls it over to
the working on section, which tells us what
pizzas we need to make. For this example,
we need one ham and pineapple, and two pepperonis. Currently, we'll start with
the ham and pineapple. Go through the steps on
the method just here and the first one is to roll
the dough. Click on this. We then need to add our sauce, pepper, cheese, add
12 pieces of ham. Finally, 12 pieces of pineapple and this is all updated on our
section just here. Once we are done,
we can add this to the oven and if you
were to make a mistake, we can also add this to waste. Click on this and then
behind the scenes, it also does a check
to make sure we have all the correct ingredients
which we need for our pizza. There's a ham and pineapple, which goes into the oven. We can move on to the pepperoni, and then once we're
done with this, we can complete our order
and move on to the next one. Also we need to keep on top of things because these orders will keep coming in as
the time progresses. This is a reasonably big project compared to what
we've built so far. But most of which you
will already know. It's just a case of
building one small feature at a time and you'll
be perfectly fine. Along the way, I will
give you a series of tasks to try things
out by yourself, but don't worry, you
are not on your own. I'll also run through
each stage too so we can compare and remember, as always, there is multiple
ways we can approach things. If we both come up with different solutions which
both work, this is fine. Inside the starter files, we have a basic starter
with our index page, which adds all of the initial
layout which we need. We also have some styling in our style sheets and
this just means we can jump straight into our
JavaScript and focus on this. Even though it looks the
same as the final project, nothing actually
works yet and we will be coding all of
this during the class. As a starter, I've also
included the pizza.svg and also a JavaScript file which is linked in
our index page, which contains three arrays. These three rays are going
to save us a lot of typing. First is a pizza's
array and inside here, we have various pizza
objects with the pizza name, a method to make
this pizza and also the required steps which we
use in the project to check if the chef has made
the correct pizza and also placed the ingredients
on in the correct order. Then just below this, some sample orders to
get the game going and we will also be generating
these dynamically too. Finally, a list of ingredients we need inside the kitchen. Great, so this is
all now ready to go. Open up this project
folder inside the browser and then jump into the next lesson where
we'll get to work on listing these orders
inside the browser.
25. Listing Orders: This video will only have
one main objective and this is to loop
through all orders and display them in the browser. Remember that just above, provided with this folder is the oldest array which
we're going to loop through and display
inside the browser. The location for this will be over on the right-hand side, in the side section. In the index page, we have two main sections. We have this main wrapper and this contains
all of the contents, which has the white background. Then the aside with
the idea of orders. For now, this just has
a level 3 heading. But what we're going to do
is to loop through all of these orders and place
these into this section. To do this, we'll create a function called
createOrdersList. This function is going to loop through the above orders array. For each one of these
items in the array, we'll construct a div, which looks just like
this section here. Certain parts of this
are going to be dynamic. For example, we'll
have the order number. This is going to be dynamic
along with the name of the pizza and also the
quantity for each line too. You don't need to worry
about these comments. These are just but a visual guide to give us an idea of what
we're going to do. We'll begin down at the bottom
by creating our function. The function is called
createOrdersList , the function keyword. The next thing is to loop over
each one of these orders. We know how to do
this. We can use a loop such as forEach. Grab our orders array forEach. Remember that forEach
is going to run a function for each
item in our array. Places function just inside. We'll give each one of these
items the value of order. Now, we need to
basically construct our elements just like we did above for each one
of these orders. We'll begin by creating
this main wrapper, which is the div. We'll add a class
called order wrapper. We'll get to work
at in our content inside. We know how
to create elements. We use document.createElements. As in the elements' tag name, which is a div inside of a variable or constant
called orderwrapper. Then add our class name by selecting the variable
name of OrderWrapper. The property called ClassName. Just as we see above, this is
going to be Order_Wrapper. So we'll just add a comment. This is the main wrapper. Then after this,
we'll add a comment. This is going to be to
add the order number. This is our first section
inside of our order wrapper. This will be a level
4 our heading. Store this inside of a constant. I remember when creating
elements like thses, we need to create
the actual element and then the content inside. So we need two variables. The first one is orderNumber L, which is shelf elements. So document.createElements. We need a level for heading. Next, the text which
is going to go inside, and this is the order number. The constant name of order number and we create this with
document.createTextNode. Since this is going
to be dynamic because each order has a
different number, which we're going to grab
from this unique ID. We'll place this inside of the backticks to
make this dynamic. First, the text of order, which is this part just here, followed by a dynamic value. The dynamic value
can be inserted using the dollar symbol
and the curly braces. First, we select our
individual order, which is stored
in this variable, and then the property of ID. As always, when creating an
element, just like this, we have two standalone pieces of information and we need to
merge these both together. We do this by
accessing the parent, which is the
orderNumberElement.appendChild, where we'll pass in
our actual contents, which is order number. This now leaves us with our
div, which is the wrapper. Then our first element, which is our level 4 heading, but we still need to add
this heading to our wrapper. Grab the Order_Wrapper and then we'll again use apendChild, which will take in our
order number element. So we've got the first
section just here, and then the next part is to
create our own order list. A quick comment, so we know
what we're doing here of great pizza UL for each order, and the wrapper so
document.createElements. The elements was
an unordered list. Places into a constant
called Pizza list. This now gives us
an unordered list, which is the main
wrapper for all pizzas. But remember, we can
have multiple list items because each order may
have more than one pizza. So because our orders have multiple pizzas
inside of an array, we again need to do a
loop such as for each. To do this, we again jump
into our individual order. We'll select the array,
which is called pizzas. Use the for each loop
to run a function for each item or each pizza
inside of the array, store this inside of a
variable called Pizza. Then we can get to work with constructing each
one of these items. Each one of these items
will be a list item. But first, we need to
create this content inside. We have the quantity such
as one, and then a dash, then a span element followed by the name of each one
of these pizzas. Jump into our function and for each one of
these items we'll create a span element to wrap our title and store this
inside of a constant. This one is order quantity L, so document.createElements. Elements is going to be the span and then next the
quantity of each one of these item,
document.createTextNode. This section needs
to be dynamics or placed in the backticks. Insert a variable. We can access the quantity by
first selecting our pizza. In each one of these pizzas, if we take a look at the array, has a property called quantity. We'll also use the
name of property soon. For this one, this
is pizza.quantity, followed by a dash
just afterwards. Thinking about this, it may
be a little bit easier if we just add this quantity
into our span. Rather than having
them one outside, we'll maybe place this
inside of an element, rather than having this
outside on its own. We'll do this by accessing
the order quantity elements.appendChild that's
in the quantity variable, followed by our pizzaName. For our pizzaName, this
needs to be wrapped also in a span element and
then the contents inside. We need to do exactly
the same as just above, we'll create a constant called pizzaNameL
document.createelement. Element is a span followed
by the pizzaName, which we need to create
with create text node, grab our individual pizza. Then just as we've seen before, we have the quantity followed
by the name property. We can access this
with pizza.name. Merge these two together.
PizzaNameL.appendChild wasn't in the text content,
which is pizzaName. Great, so we've got two
separate spans here. We have our first span, which is wrapping our
individual number or the quantity of pizzas. Then a second span which
contains our pizzaName. Both of these items need to
be merged into a list item. Then the list item needs
to be added to our parent. So let's get to work.
As a new comment just to keep this clear. This one is create a list item. Show the quantity and pizzaName. First elements stored in a
constant called pizzaItem, document.createElement.
This was a list item. We've got our surrounding
list item and then we need to merge our two
elements from above. The quantity which
is this variable, and also the pizzaName. Let's grab our pizzItem. Since we're appending
multiple child elements, we can simply use append and
that's now our first one, which was the order
quantity element. Then the pizzaNameElement.
We're almost done now, we have our list item will be created without two pieces of content inside and now we need to add these to our
unorde