JavaScript: The Complete Crash Course
By Boot dev
Summary
Topics Covered
- Var leaks beyond blocks
- JavaScript inescapable for web
Full Transcript
Bootdev is finally going soy dev. That's
right. We've created a complete JavaScript course. So, break out your
JavaScript course. So, break out your oat milk latte, favorite beanie, and get ready for a performative coding session at your local coffee shop. Okay, but in all seriousness, this is a really in-depth JavaScript course. And you're
going to be guided through the whole thing by Jess, also known as Coder Coder, who happens to be one of my favorite developer YouTubers out there.
Here's the thing. You just can't escape JavaScript. It's on the front end, it's
JavaScript. It's on the front end, it's on the back end, and some crazy people even use it to define their cloud infrastructure. It's fair to say it's
infrastructure. It's fair to say it's very popular. So, we've recorded this
very popular. So, we've recorded this 7hour course to be the last JavaScript course that you'll ever need. We've even
spent over 40 hours meticulously animating the really tricky bits so that if you're a visual learner, it will really stick. Now, this course doesn't
really stick. Now, this course doesn't just cover the basics. We won't be building Baby's first to-do app with HTML, CSS, and JavaScript. We're going
to go very deep on all the fundamentals and cover a bunch of the advanced topics that frankly most junior developers only have a shaky understanding of at best, but we will start off slow. Jess is
going to take you through variables, comparisons, functions, and objects. You
know, all the easy stuff that you need to get started with JavaScript syntax.
Then she'll cover classes, prototypes, and prototypical inheritance. This is
one of those JavaScript specific quirks that a lot of devs are aware of but honestly don't even understand how it works under the hood. Next, she'll go over collection types and error handling. She'll even go in depth on
handling. She'll even go in depth on promises, the new async await syntax, and even dive into how the event loop works in excruciating detail. Finally,
she'll cover some of the different JavaScript runtimes like browsers, node, dino, and bun, and then finish it all up with ES6 modules and their associated foot guns. Now, one unique thing we're
foot guns. Now, one unique thing we're trying with this specific course is well, like all of our other courses, it is written by longtime JavaScript developers, including myself. But Jess,
who's doing the walkthrough, is actually new to some of the more advanced stuff in this course. Obviously, she's a fantastic developer, but on her channel, she's more been focused on the design
side with HTML and CSS. So, later in the course, she'll actually be learning a few new things alongside you as she explains it. So, let's also console log
explains it. So, let's also console log since I'm really not sure if I'm doing the right thing here. Basically, it's
made the walkthrough super relatable and perfect for you if you're a beginner because Jess knows exactly what you're going through. If you've never written
going through. If you've never written JavaScript before, this is going to be a fantastic and most importantly thorough introduction to the language for you.
And if you have written JavaScript before, but there's still a lot about the language that feels a bit arcane and magical, then this course is going to demystify a lot of that stuff and give you a lot more confidence in the code
that you write. Now, before we jump into the content, it's important to know that this course on Bootdev and the walkthrough video here on YouTube are totally free. So, head over to boot.dev
totally free. So, head over to boot.dev and make a free account if you don't already have one, so that you can follow along as you watch. If you just sit back and watch Jess complete all the lessons
without doing anything, you're not going to learn much. Now, while all the text and video content of this course is free, if you do like the interactivity that comes on the Bootdev website, the
stuff like lesson submissions, progress tracking, the ability to chat with Boots, and certificates of completion, then consider buying a membership. If
you use Jess's code, coder coder, you'll get 25% off your first year of an annual plan, and you'll be directly supporting her and her channel. Now, we're just about to start chapter 1, but before we
do, I need to confess. Okay, I actually lied about this video being free. There
is a small price, a trifle, really. I
just need you to like and subscribe to the video. It really does help us to be
the video. It really does help us to be able to continue to make these massive highquality walkthroughs and publish them on YouTube. So, thanks in advance for doing that. Now, time to talk about
some JavaScript.
All right, and here we are at learn JavaScript for developers chapter 1, lesson one. And we are mainly going to
lesson one. And we are mainly going to be writing code in our browser in this really cool integrated tool here. But
we're also going to be using the local machine and the boot.dev CLI tool for some of the lessons. So in this course, what we're going to be doing is building a SAS app called Texio to send text
messages to customers. And each lesson has an assignment. And this assignment is about the console log function and it prints text to the console. So what we want to do is we want to have the
console print starting textio server instead of hello there. So if we look on the right side in the um tool that they have here, you write the code up at the top panel and then you can click the run
button and it's going to run execute the code and then give you you know the result in the bottom. And you can kind of move this up a little bit so we can see that better. So I'm just going to
click run. And then it's printing the
click run. And then it's printing the hello there message. So let's copy that text and paste it inside the console log
function. So now when we click run, it
function. So now when we click run, it says starting textio server, which is what they asked for. So when we think the code is correct, then we can go ahead and click the submit button and
then boot.dev is going to check your code and make sure it's correct. So
let's click submit.
All right, it says it's correct. So, we
have basically finished this lesson and we can move on to the next one. Now,
this next lesson deals with some of the basic types in JavaScript, meaning how you can store and work with different kinds of data. So, the basic types in JavaScript are a boolean, meaning true
or false. Then you can have a string, so
or false. Then you can have a string, so a sequence of characters, meaning letters, numbers or symbols. You can
also have a number, so you can have an integer, which is a whole number. Or you
can have a fractional number which means a number with a decimal. And then you can have undefined which means that you're going to create a variable but you just haven't assigned a value to it yet. And there are some other types.
yet. And there are some other types.
These are just the basic types. So when
you declare a variable you are creating it and you're going to give it a name and then usually you're going to set it to a value. So we can see some examples
here. So for example, this first one is
here. So for example, this first one is is tall and it's being created with the var statement like the other variables here and we've set it to true which means it's going to be a boolean. Then
below that we have another boolean is cool set to false. Then you have a name which is set to Alice which is making it a string. Then we have a number um an
a string. Then we have a number um an integer and then we have another number which is a fractional number because it has a decimal point. And then at the bottom we have an undefined variable of brain size. So if we look at the
brain size. So if we look at the assignment, what we want to do is we want to give values to these different variables to make them these types. So
if we look at the first one, SMS sending limit, we want it to be a number and then we want the next one to be boolean and then string and then undefined. So
let's check out our code that we have here on the right. And I'm just going to move this up a little bit so we can see better. And before making any changes,
better. And before making any changes, I'm just going to run this code and see what the results are. So when we hit run, it tells us that all four variables are undefined. And that does make sense
are undefined. And that does make sense because if we look up in the code, they've all been created and named with the var statement and a name, but they've not been set to any kind of
value. So this makes them all undefined.
value. So this makes them all undefined.
So I'm going to start with the first one, SMS sending limit. And we want it to be a number. So we can assign it by setting equal to a number. And I think
we can just pick any number. I'm going
to say 20. So I'm going to run the code again just to see if anything has changed with SMS sending limit. So let's
click run. And now we can see that now SMS sending limit is a number. So this
does seem to be working. And then next up we want has permission to be a boolean. So true or false. So again
boolean. So true or false. So again
we'll say var has permission equal sign and then we can say true or false. I'm
just going to say false. So let's run it again. And now we can see has permission
again. And now we can see has permission is a boolean. So next up we want username to be a string. So equal and
then we can say in quotes um any string.
I'm going to say coder coder.
Hit run again. And now we can see that it has been created as a string. And
then nothing is undefined. So because it was undefined by default without being assigned we probably want to leave it as undefined. Okay. So, I think that we
undefined. Okay. So, I think that we have all our code that we need. So, now
let's click submit and see if we got it right.
And we did. All right. So, let's go to the next lesson. All right. Next, we're
going to look at let and const, which are the new ways to declare variables.
So, these new keywords use the same syntax as we did with var. So instead of saying var my skill issues equals 42, we can create this as a let and say let my
skill issues equals 42. Or we can use const which is short for constant and say const my skill issues equals 42. Now
the difference between let and const is that you cannot reassign a constant variable after you've sort of declared it initially otherwise you'll get an error. You can see here in this example
error. You can see here in this example we created const my skill issues equals 42 and then we tried to reassign it and give it a new value but this will throw
an error assignment to a constant value.
However, in comparison if you're using let you can reassign the value. So we've
created my skill issues here using let and then reassigned it and change the value to 43 and it will not throw an error. So, as it says here, use let for
error. So, as it says here, use let for variables that you will need to reassign and then use const when you won't. So,
you might be wondering if var still works, then why shouldn't we use it? You
know, what's the problem here? So, the
main issue with var is that it is function scoped as opposed to being block scoped. And to get into what that
block scoped. And to get into what that actually means, let's look at the code example that they have here. So, a block is code that's contained within curly braces in various statements. For
example, this if statement that we have here has curly braces and inside the curly braces is var my skill issues equals 42. So inside here is the block
equals 42. So inside here is the block and this variable is created with var.
So as we said earlier, var is function scoped which means that the variable is scoped or accessible even outside of this code block. So we've declared the
variable inside the code block and then we have called the variable and written the value of it to the console log function outside of the code block and everything works fine. Now in this
example we don't have an explicit function. So that means that the
function. So that means that the variable is contained within the global scope meaning you know everywhere basically and you might think that this would be a good thing right you know you created this variable you can call it
anywhere else in your code but that freedom can lead to confusion. For
example, if you have a global variable that's getting used, you know, in multiple different places in your codebase, you are inevitably going to have some unexpected results if it's, you know, getting overwritten when you don't want it to and other kinds of
conflicts like that. So, let's look at the let and const keywords. They are
more limited to the block scope. So if
we go to the next code example here, we similarly we've created two variables inside the if statement, but instead of var, we're using let and const. And then
we're trying to call them in the console log functions outside of the code block.
But these are going to throw issues.
These are going to throw errors saying my skill issues is not defined. My con
skill issues is not defined. That's
because these variables were defined inside this block. So they basically don't exist. They're not accessible
don't exist. They're not accessible outside of the block, which is why they're returning as undefined. So with
all that in mind, let's take a look at the assignment here. So in the assignment, we have a bug and it is sending two birthday messages, which we don't want. So we want to fix the var
don't want. So we want to fix the var declarations so that each variable has the correct scope and behaves as expected. So in the code itself, let's
expected. So in the code itself, let's see what's going on. So first up we have a message text variable that says welcome to textio and then we have a
variable for is birthday and it's set to true. So this is a boolean. Then after
true. So this is a boolean. Then after
that we have an if statement. So if is birthday is true we have inside this code block changing the message text to happy birthday or rather it's redeclaring message text to say happy
birthday and then we have some console log functions sending birthday message and then whatever the message text is.
Then outside of the is birthday code block, we have some more console log functions here sending the welcome message and then whatever the message text variable is. So let's start by
trying to run the original code and then just seeing the result. So we clicked run and it says sending birthday message. Message text is happy birthday.
message. Message text is happy birthday.
Sending welcome message but then the message text is happy birthday again instead of what we wanted which is welcome to text you. So it's doing this because we're using var for the message
text variable. So it's function scoped
text variable. So it's function scoped meaning that the change inside the code block here is going to affect everywhere else including outside the block with
the console log message down at the bottom. So we want to make these
bottom. So we want to make these variables block scoped so that the birthday message change is only going to happen inside the if code block. So what
we can do is we can instead of declaring the variables using var we can use say const message text equals welcome to textio
and then for is birthday I'll just set it to let just for the sake of using something different and then inside the birthday code block again I'm going to say const and then we
have our console aug messages so we'll leave that as is. All right. So now we have declared our variables using either const or let. Let's run our code and see how it looks. So now we have sending
birthday message and it says happy birthday. And we have the welcome
birthday. And we have the welcome message saying welcome to text you. So I
think the code's doing what we want.
Let's submit it and see if we got it right.
Cool. And let's move on to the next lesson. Now if you know anything at all
lesson. Now if you know anything at all about me, you know that I don't like JavaScript very much. But I do write a whole lot of it. And it's not because I
want to, it's because I need to. It's
the only language that runs natively in the browser. And honestly, that alone
the browser. And honestly, that alone has been enough to propel it to meteoric heights of popularity. Yeah, I know there's web assembly, but that still doesn't really work for most use cases.
Sure, as a web developer, you have 20 or 30, honestly, different choices for back-end languages in your stack, but you're pretty much forced to use JavaScript if you're working on the web,
at least for your front end. Now,
JavaScript is not without its faults.
It's not statically typed, which I honestly kind of hate. And there's just so much legacy code out there that needs to be updated. Code that uses the var syntax for declaring variables. code
that doesn't use promises or async await and just gets you deep into callback hell. The weird quirks with double
hell. The weird quirks with double equals versus triple equals for comparisons. And the fact that it just
comparisons. And the fact that it just behaves so differently across different browsers and runtimes makes it not the most fun language to work with. But
there are some great things about JavaScript. The chief among them being
JavaScript. The chief among them being well, you're kind of forced to use it, so you better get used to it anyways.
And hey, at least it's not OAML. Like we
actually can write good production code in JavaScript. It is possible. I mean
in JavaScript. It is possible. I mean
every technology company for the most part has it somewhere in their stack. So
there's tons of jobs available if you have JavaScript on your resume. It also
uses a pretty standard C style syntax.
So if you're coming from another language, JavaScript usually looks pretty familiar. And almost all of the
pretty familiar. And almost all of the built-in features to the language are built with the web in mind. So, if
you're doing web development, it just comes with a lot of tools out of the box to do tons of crazy things with strings, which I mean, strings are really kind of the backbone of the web. And because
it's really the only language that works on the front end, it's also kind of the only language that works on both the front end and the back end. Meaning, you
can do full stack development in a single language. And while it used to be
single language. And while it used to be really, really rough to work with, so much time and money has been invested by giant tech companies to making both the
developer experience of JavaScript better, but also the runtime performance. So, there's just a lot of
performance. So, there's just a lot of money and time going into making JavaScript and the JavaScript ecosystem better. It also genuinely does have
better. It also genuinely does have really good support for asynchronous programming, something that doesn't always work great out of the box in languages like Python or Ruby. Now, it's
far from my favorite language, but I do genuinely owe a big portion of my career to JavaScript, and I have been using it for many years. If I didn't understand JavaScript, I'd probably be relegated
just to the back back end of the stack where I don't touch anything on the front end. And almost half of my roles
front end. And almost half of my roles have been honestly full stack roles.
spend about half the time on the back end, but half the time I am jumping into the front end and looking at some JavaScript code. And honestly, this idea
JavaScript code. And honestly, this idea of going full stack is becoming more and more common in the jog market, at least according to the recent Stack Overflow surveys. So, good luck. Mastering
surveys. So, good luck. Mastering
JavaScript isn't necessarily easy. Not
the hardest language in the world, but it will be useful. It is everywhere. All
right. So, why are we learning JavaScript? Well, the main reason is
JavaScript? Well, the main reason is that JavaScript is the language of the browser. So every website, no matter
browser. So every website, no matter what programming language or framework that you use to build it, is going to ultimately load with HTML, CSS, and JavaScript. So JavaScript is here. It's
JavaScript. So JavaScript is here. It's
everywhere, and it's not going away anytime soon. Now, there are definitely
anytime soon. Now, there are definitely some parts of JavaScript that are a little tricky to deal with. It's not
statically typed, although TypeScript helps with the type checking to add to that, and it can also be kind of quirky.
But the upsides are that because every website or web app has to use JavaScript in some form, that means companies have to use it, which means that it can be a very marketable skill if you're looking
for a developer job. Also, with NodeJS, you can run JavaScript on the server.
So, you can technically be a full stack developer with JavaScript. All right, so let's check out this quiz that we have here for the lesson. Why is JavaScript commonly used for web development? So,
let's go through the choices here. It is
faster than all other programming languages. That's very bold. I don't
languages. That's very bold. I don't
think that's the answer. It's basically
the only language I can run in a web browser. I think that's true. Um, but
browser. I think that's true. Um, but
let's look at the other choices just in case. It's a statically typed language.
case. It's a statically typed language.
We also know that's not true. And then
it has no quirks or legacy issues, which is also untrue. So, I'm going to say it's basically the only language I can run in a web browser.
All right. Lesson five, comments. So in
every programming language including JavaScript, you have the ability to write comments right in your code. So
this is for notes or documentation that you're writing for humans and it's you know not supposed to be code that gets executed. And what you have to do is you
executed. And what you have to do is you have to designate whatever you're writing as a comment usually by using some symbols. So we can see some
some symbols. So we can see some examples here. We can have a single line
examples here. We can have a single line comment up at the top and you do that by starting that line with two forward slashes. So, this means this line is
slashes. So, this means this line is going to get ignored and won't try to be run. And you also might have, you know,
run. And you also might have, you know, multi-line comments. And it would, you
multi-line comments. And it would, you can probably imagine that it would be kind of annoying to have to write two forward slashes at the beginning of every single line if you have, you know, a bunch of lines. So, you can enclose
all those lines of your comment within a forward slash, an asterisk at the beginning, and at the end another asterisk, and then another forward slash. So, this way, you're kind of
slash. So, this way, you're kind of surrounding your comment with these symbols. and then it won't get run. So
symbols. and then it won't get run. So
let's check out this assignment. So it
says the new intern on the team messed up their documentation comment. Fix the
syntax so that their comment does not include the code. So you can see here if I move this over we have the comment that is up here
and then we have you know what looks like the actual code down here. So you
can see with the syntax highlighting the green is for the comments and it looks like the entire thing is in a comment.
So just for the sake of curiosity, let's run this code as it is and see what happens.
So it says syntax error unterminated comment which means the comment started but it never ended. So let's look at our code again and see what we need to do.
All right. So for the first line, attention this is a single line comment with the two forward slashes. So that
seems fine. And then looks like we started a multi-line comment here with the forward slash and an asterisk. Then
we have a few lines of comment here. And
then we have an asterisk, but it doesn't have that closing forward slash. So this
is why the rest of this code was included as a comment. So if we want to close that comment, let's add a forward slash after the asterisk. Now we can see the syntax highlighting um is telling us
this is the actual code, not a comment anymore. And let's try running this. So
anymore. And let's try running this. So
now we can see the actual message from the code here and the comment is not getting executed. So everything looks
getting executed. So everything looks pretty good to me. So let's submit this and see what happens.
Nice. All right. So lesson six, we are going to look a little bit more at numbers in JavaScript. So in a lot of other programming languages, the language is going to have multiple types
of numbers. For example, in Python, you
of numbers. For example, in Python, you have integers and floats for decimals.
But in JavaScript, all numbers, whether they're integers, negative numbers, or have decimals, those are all going to fall under the number type. So if we look at the code example here, we have
2 5.69 negative 5.42, and they are all that number type. And you can also do math.
number type. And you can also do math.
So with addition, you can do the plus sign, you can subtract with the minus or the hyphen sign, you can do multiplication with the asterisk, and then you can do division with a single
forward slash. So with all that in mind,
forward slash. So with all that in mind, let's check out the assignment. So it
says textio tracks the number of messages sent for different types of notifications. So between the comments,
notifications. So between the comments, create a total messages sent variable containing the total number of messages sent. And then create an average
sent. And then create an average messages sent variable containing the average number of messages sent across all types, which I'm assuming are the
four types here that we have um on the top. So let's do the total messages sent
top. So let's do the total messages sent part first. So what I'm going to do is
part first. So what I'm going to do is copy variable name from the example and then we're supposed to write the code here.
So we want to declare our variable for total messages sent. So I'm going to say const total messages sent. And then I want to set it equal to the total number
of messages. So basically adding all
of messages. So basically adding all these other ones together. So, I'm going to copy and paste each of the
variables that we have at the top, reminder messages, welcome messages, and then the last one, support messages.
Let's actually test the code for total messages sent and make sure it seems to be the right total. So, I'm going to run the code.
And then at the bottom, it says total messages equals 40. So, if we kind of eyeball the numbers that we got here, that looks like about 40. I can't do super fast mental math. And then average
message sent is not defined because we haven't set it yet. So, let's work on that.
So, let's create a new variable. So,
const we'll say average messages sent and equals. And then we need to figure out
equals. And then we need to figure out the average. So the average is going to
the average. So the average is going to be um it says the average number of messages sent across all types. So we're
taking the average of each of these four types here. So to do the average we want
types here. So to do the average we want to take the sum which we conveniently have with total messages sent and we want to divide it by the number of um
types of messages which is four.
So I'm going to say total messages sent divided by with a forward slash and then I'm just going to hardcode in four for
the four different types. So now let's run our code again. Total messages is 40 and then average messages is 10. So
again if we kind of eyeball looks like 10 seems to be a pretty good average number for that. So I think we're good.
And let's submit this code and see see how we did.
Nice. And now we're doing a numbers review. So it's telling us that in
review. So it's telling us that in JavaScript all numbers are just number types. There's no distinction between
types. There's no distinction between different types of numbers. And and then it's kind of a little review of the different arithmetic that you can do with the numbers in JavaScript. All
right, so let's check out this quiz. So
in JavaScript five is a blank while 5.5 is a blank. The choices are number number which I think is what it is integer number integer float float
integer. So in JavaScript every number
integer. So in JavaScript every number is a number and we got it right. All
right. So lesson eight increment and decrement. And I have to admit that I
decrement. And I have to admit that I had to look up how to pronounce this word because I don't think I ever had to say this out loud before. Um, so in Python, we use the plus equal sign
operator to increment or add a number.
The operator works in JavaScript, but JavaScript also has a plus+ operator when you only want to increment by one.
So that's kind of handy, right? So
here's some example of the incrementing.
So we're starting with bootdev course rating at four. If we do the plus+, we'll increment by one. So adding four + 1 is five. And then we can also
increment by any number. So plus equal 5. So adding 5 to 5 is 10. And then we
5. So adding 5 to 5 is 10. And then we can do the same thing for subtracting using the minus minus operator to decrement by one or any number that you
want like five in this second example here. So let's check out the assignment.
here. So let's check out the assignment.
So it says textio tracks how many messages have failed to send on a given day. Use the plus+ operator in between
day. Use the plus+ operator in between the comments to increment the numbum failed messages. So if we check out our
failed messages. So if we check out our code here, um we are declaring numfailed messages as 1 1336 and then we want to um use the
plus+ operator to increment. So you
might notice that um when we declare the numfailed messages variable, we're using let and that's because we want to change the value of numfailed messages. If we
used const for this, then it would throw an error when we tried to change it. So
that's one example of when you want to use select. I'm going to copy numfailed
use select. I'm going to copy numfailed messages and we're going to reassign the value to be uh num messages
plus plus and that should add one.
So let's uh run this code and see how it looks. And now it's telling us that we
looks. And now it's telling us that we have 1337 failed messages. So it looks like it did work. All right, submit and see how we did.
All right. All right. Lesson nine,
undefined versus undeclared. So these
are two concepts that can seem very similar, but they are actually two different things. So when you create a
different things. So when you create a variable, you are declaring it. And then
often times you may also assign a value to that variable, which is what we mean by defining it. So if we look at the code example here, just scoot this over.
We are declaring creating the favorite Sanderson character variable using let and then we are not setting a value to it. So we it is going to be undefined
it. So we it is going to be undefined and then if you call that variable which is undefined um with a console log function then it is going to return undefined. Now in comparison if you do
undefined. Now in comparison if you do not create the variable at all in the first place it's going to be undeclared because it's not been created. It
doesn't really exist. And if you try to call a variable that you have not declared it is going to throw an error saying favorite roles character is not defined. And this wording is a little
defined. And this wording is a little bit confusing as you might imagine because it's not undefined. The variable
was never declared in the first place.
So the wording is a a little bit inaccurate. Um so yeah, welcome to
inaccurate. Um so yeah, welcome to JavaScript. And then here's another
JavaScript. And then here's another quirk. So if you create a variable using
quirk. So if you create a variable using const but you never set a value to it, it is going to be undefined. But that
doesn't make sense because you know once you create a con, you can't change a value of it. So there's no really purpose in doing this. And if you create if you run code like this, it is going
to throw an error saying syntax error missing equal sign in const declaration because you never declared um you never defined the value of this variable. And
you can get around that error by saying, you know, constant character equals undefined. But again,
there's really no purpose to writing code like this because you can't change the value. So this is I'm assuming a do
the value. So this is I'm assuming a do not do this kind of thing. So with that in mind, let's check out the assignment.
I'm going to slide this panel back over.
So the assignment says, create the missing variables used in the console log calls so that they are declared but undefined. And then make sure the code
undefined. And then make sure the code runs without errors. So we want these variables to be declared, meaning we create them with a let. But we don't want to set a value to them. So they're
going to remain undefined. What we want to do is we want to declare the variables with let. So sent messages is the first one. And then we're not assigning a value to it. So they remain
undefined. And then do the same thing
undefined. And then do the same thing with this next one. And then the third one. All right. So now let's run our
one. All right. So now let's run our code. So now it's saying sent is
code. So now it's saying sent is undefined. Delivered is undefined.
undefined. Delivered is undefined.
Failed is undefined. So they are declared but they are undefined which is what I think we want. So let's try submitting this.
Nice. All right. Lesson 10. So null
versus undefined. So these are another two concepts that seem very similar, but they're actually different things. So
undefined, like we learned earlier, means that we've declared a variable, but we just haven't given it a value. So
there is no value at all. It doesn't
exist. And null is slightly different because it doesn't not exist in the way that undefined doesn't exist, but it's sort of like a value of nothing. It's
empty. So if we look at the code example here, this is declaring the my name variable, but it's not assigning it a value. So it's going to be undefined.
value. So it's going to be undefined.
And then in comparison, if you want to use null um as a value, you have to explicitly assign it. So in this example, we are declaring the my name
variable and then we're setting it equal to null. And then when you use it in the
to null. And then when you use it in the console log function, it's going to return null. And then there's a little
return null. And then there's a little bit of a description about um this weird quirk with JavaScript where if you set something to null um it's going to return an object type which doesn't
really seem very intuitive cuz you know it's null but this is just one of those historical quirks with JavaScript. And
then here he's saying that he personally will use undefined almost everywhere except in those cases where you have to use null for whatever reason. Maybe
you're using some thirdparty code that forces you to use null because you know they're doing it. All right, so let's check out the assignment.
Textio has lots of legacy code that checks if specific values are null. Just
to be safe, the engineering team decided on a standard where variables that aren't declared with a specific value should be set to null instead of a default undefined. So our assignment
default undefined. So our assignment here is to fix the code so that each variable holds a null value. So, as we learned up at the top, to use a null value, you have to explicitly assign it
using the equal sign. So, we're just going to do the same thing here. So, let
set messages equal null. Let delivered
messages equal null. Let failed messages equal null. And let's run this. See what
equal null. And let's run this. See what
happens. And it says sent is null is true. Delivered is null is true. Failed
true. Delivered is null is true. Failed
is null is true. So, I think we are good to go. All right. Let's check this out.
to go. All right. Let's check this out.
All right. All right. So, as we looked at
right. All right. So, as we looked at earlier, JavaScript is a dynamically typed language. The variable types are
typed language. The variable types are only known at runtime. So, this means you declare your variable, you set a value to it, and then the type is going to be determined by the value that you've assigned to it. Now, in addition
to that, JavaScript is also weekly typed. So, this means that even after
typed. So, this means that even after you've created your variable and had its type um set, that type can actually change depending on what you do with that variable. So we can look at this in
that variable. So we can look at this in this code example here. So in the first line we've created answer to life and we've set that to be a number 42. Then
below that we've created another variable answer to the universe and we've set that to be 42 also except that this is a string instead of a number. So
what's going to happen when we try to add the number 42 to the string 42 in JavaScript? Well, JavaScript is going to
JavaScript? Well, JavaScript is going to think that you wanted these to both be strings and it's going to put them next to each other and return a value that's a string instead of trying to add the
numbers together. So, this means that
numbers together. So, this means that the answer to life variables number type was changed to a string type because we tried to add it to another variable which was a string. So, with that in
mind, let's check out the assignment.
All right, run the code in its current state. Notice the very odd sum. So let's
state. Notice the very odd sum. So let's
take a look at the code here. So we are adding total sent messages which is 100 a number to total received messages
which is 50 a string. So let's run this and see what happens. All right. So it
says total sent messages is 100 which is up here. Total receive messages it says
up here. Total receive messages it says 50 which is a string and then total messages instead of you know 150 it says 100 and then 50 right next to it. So fix
the error in the code by ensuring that the value matches the correct type as you would expect. So my guess is we would want to change this 50 string to a
number so that it matches the 100 number and then they can be added together like numbers and get the correct total. So
let's try to run again.
All right. So now we got 150 messages as a total. So I think this is doing what
a total. So I think this is doing what we wanted it to. All right. Submit.
Nice. Now when we're working with variables, we can declare them on separate lines like this example here.
Or we can actually declare multiple variables on the same line. And you
separate them with a comma. And I guess you don't have to type let more than once. So this is what we're going to do
once. So this is what we're going to do in this assignment. We need to declare a con called average open rate and a con called display message on the same line.
And we want to initialize them with the following values. All right. So let's
following values. All right. So let's
scoot this over a bit. So let's copy that first one. Average open rate const.
And this one is 0.23, and the other one is display message equals. And then we're just going to
equals. And then we're just going to copy this message and set it to be a string. Okay. Okay. So, let's run.
string. Okay. Okay. So, let's run.
Average open rate 23 display message is the average open rate of your messages.
So, that looks pretty good to me. Let's
submit this.
All right. JavaScript speed. What it's
saying here is JavaScript is not as fast as non-garbage collected languages like C, Rust, or Zigg. Um, it's typically just in time compiled versus ahead of time compiled like Go or Java. but it's
going to be faster than interpreted languages like Python or Ruby. And then
JavaScript runs on a single thread, but it does have support for asynchronous programming. All right, so we want to
programming. All right, so we want to figure out what applies to JavaScript here. So this is going to be garbage
here. So this is going to be garbage collected, singlethreaded, and I'm going to assume just in time compile. So I
think yeah, I think number two, there we go, is the answer there. And we're
talking a little more about strings here. So, in JavaScript, in non-mplated
here. So, in JavaScript, in non-mplated string, you can write them with either single or double quotes. They both work the same. You can use whatever you
the same. You can use whatever you prefer, but the most important thing is to just be consistent. So, if you use single quotes, make sure you use it everywhere. Same thing with double
everywhere. Same thing with double quotes. Um, and if you're working on a
quotes. Um, and if you're working on a team, then you're probably just going to have to follow whatever um styling conventions they're already using. And
indexing. So indexing is how you can access you can kind of pick out individual characters that are inside a string and with programming numbering
starts at zero. So if we look at this code example here the string is hello. So there's 1 2 3 4
five letters in hello but we start with zero. So the first letter is zero. E is
zero. So the first letter is zero. E is
1, L is 2 L is three and then the last letter O is four. And the last character can also be referred to as the length of
the string, meaning the number of letters. So 1 2 3 4 5 minus one. 5 - 1
letters. So 1 2 3 4 5 minus one. 5 - 1 is four. So that's how you can refer
is four. So that's how you can refer easily to the last character in a string if you don't know exactly how many letters it has or how many characters it has. Okay. So let's look at the
has. Okay. So let's look at the assignment here. Follow the instructions
assignment here. Follow the instructions in the comments on lines 3, 5, and 7 to log info about one of Texio users email addresses. We want to print the first
addresses. We want to print the first character in the string here. So kind of following the code example that we had here, I'm assuming we want to console
log. So we want to get from the string
log. So we want to get from the string email the first character. And like we said, numbering starts at zero with most programming languages. So we're going to
programming languages. So we're going to do that. And then we want to print the
do that. And then we want to print the last character in the string. So console
log email.
And in here we need to write email length minus one and then print the entire string. So let's run this and see how it
string. So let's run this and see how it looks. All right. So the first character
looks. All right. So the first character is s which is correct. Last character is m in the.com and then the entire string stub@gmail.com
is there.
And there we go. All right. Lesson 15
template literal. So, I love these because they allow you to work with strings and also combine them with variables. So, you can have dynamic data
variables. So, you can have dynamic data or information displayed in them. And
it's just a lot more efficient than what you might have to do otherwise. So, in
this example here, um, we have a string that we want to print. The shade is blank, but instead of blank, we're going to set it to be the value of this
variable shade of red of 101.
So this is just a lot better than you know using a bunch of plus signs and sets of different quotes in order to combine you know the parts of the string with the variable with a more string
etc. It gets it just gets very messy looking. Um, in addition to that, you
looking. Um, in addition to that, you know, in the real world, I could see, you know, these colors here. You might
have a hundred different colors, not just shade of red. And if you want to print a message that loads that variable value in it, it's going to be extremely inefficient if you have a 100 different,
you know, strings all reading the shade is 101 or the shade is whatever. So,
it's going to be a lot more efficient for those 100 or however many different colors if we use these template literals. So we can just change the
literals. So we can just change the value of what we want to put in that string depending on what we need in the program. So um for syntax wise the
program. So um for syntax wise the template literal have to start and end with a back tick. So that's what's going to surround you know the string with the
variable or variables inside and then inside the back ticks any variable is going to be inside a dollar sign and then curly brackets and then it's going
to be cast to a string type. Okay. So in
this assignment, we want to create new variable message. We want to assign it
variable message. We want to assign it to this string, but we're going to replace the name with the name Saul Goodman that we have over there. And we
have open rate, and it's also going to be replaced with, you know, this open rate number. So let's create our
rate number. So let's create our variable. Let message
variable. Let message equal. And then we said it has to start
equal. And then we said it has to start and end with back tick. So let's add those in first. Then we're going to copy the string. And we want to replace name
the string. And we want to replace name with the name variable. So dollar sign curly brackets. And then I'll just type
curly brackets. And then I'll just type it in here, name. And then we'll do the same thing with open rate. So copy paste and then open rate. Okay. And then it's
going to print that to the console. So
with that in mind, let's try this out and run and see how it looks. Hi Sol
Goodman, your open rate is 30.5%.
So that seems pretty good to me. All
right, I think we are going to try to submit that. And we got it and got a
submit that. And we got it and got a bunch of different achievements as well.
All right, and it is quiz time here. So,
Java versus JavaScript. A very common misconception is that Java and JavaScript are the same or similar and they are not the same. They're not
really similar, I would say, at all.
Java is a JavaScript as car is to carpet. It's pretty true. Yeah. So, Java
carpet. It's pretty true. Yeah. So, Java
is a statically typed object-oriented language. So on and so forth. Um,
language. So on and so forth. Um,
JavaScript is a dynamically weekly type language that runs natively in the browser. So, it's very different from
browser. So, it's very different from Java. The only reason it was named
Java. The only reason it was named JavaScript was back in the day when it was created in the '90s, Java was very popular and the creators wanted to get a
piece of that marketing value. So, #
branding. All right. So, in the quiz, JavaScript is just another name for Java. I'm sure you all agree with me.
Java. I'm sure you all agree with me.
False.
And then continuing on with the quiz, JavaScript came blank Java before or after. JavaScript came after Java. All
after. JavaScript came after Java. All
righty.
Semicolons in JavaScript. So yes, when you're writing in a language like C, C++ or Java, you need to use a semicolon at the end of all your statements so that the compiler knows that you know the
statement is finished. And you can have them on different lines, but you can also have multiple statements on the same line as long as they each end with that semicolon. Now, with JavaScript,
that semicolon. Now, with JavaScript, the semicolon is actually optional, but I think most people, and I I do this as well, they still use semicolons at the
end of lines just because you want to make things as clear as possible as well as avoid any errors that could arise from that. So
from that. So in the assignment here, let's fix a bug in the provided two-statement program on a single line. Okay, so run the code. It
says syntax error, unexpected token.
So we want to stay on that single line, but we want to fix the bug, I would say, by adding semicolon after the first
console log and the second one. So now
when we run, we got our two console log messages. So, I think we're good.
messages. So, I think we're good.
All righty. So, we are getting toward the end of chapter 1 here. So, string
encoding. Um, in JavaScript, strings are made up of characters that are usually represented by one 16- bit number, two bytes. Um, however, some characters like
bytes. Um, however, some characters like emojis require more than 16 bits. So,
JavaScript is going to use two 16- bit numbers to represent emojis like these.
This is just kind of like an FYI, but if you do use emojis in your JavaScript strings, just be aware that some of these characters are going to take up more than one UTF character. So, run the
given code.
Let's move this up here. So, the
constant name, which is the string boots, the UTF-16 unit length is five, and that's cuz there's five letters. And
then the constant name character is also the same. It's five five characters
the same. It's five five characters long. So, we're just going to compare
long. So, we're just going to compare that with this bear emoji here.
So, we'll replace that. And now, let's run. So, this is different. So, the bear
run. So, this is different. So, the bear emoji like we were reading, it's created by two UTF characters, I guess you could say, but then the actual constant itself
is going to be just one character. So,
yeah.
All righty. So, when you're naming variables, when you're programming, you can't have a space in the variable name, but you often may want more than one
word in that variable name. So, because
of that, there are different approaches to how programmers create variable names. So for example um in JavaScript
names. So for example um in JavaScript most people will use camelc case meaning the first word starts with lowerase and then you alternate going to uppercase and then you know if you need more lower
case and then uppercase. Then we got snake case and you know it's a snake because you separate each of the words with an underscore which looks like a
snake and then Pascal case which is just starting each word in the variable name with an uppercase letter and then screaming snake case which I think is
pretty self-explanatory.
So in the little quiz here, the JS community generally prefers camelc case.
Nice.
And we are now on to chapter 2, comparisons. So this first lesson deals
comparisons. So this first lesson deals with conditionals. So with if
with conditionals. So with if statements, you can check whether one or more conditions is being met. And it's
going to return either true if it is happening and then false if it's not happening. So in this first example, the
happening. So in this first example, the if statement has a condition inside the parenthesis and we're checking if the height is greater than four. So height's
going to be a number. And if the height is greater than four, it's going to return this message saying you are tall enough. And you can also check for
enough. And you can also check for multiple conditions. So in the second
multiple conditions. So in the second example, we have the first condition. If
height is greater than six, you are super tall. And then with the second
super tall. And then with the second condition we want to check for, you have to say else if. So the first one is what starts with if the second and then if you have multiple other ones have to
start with else if. So it else if height is greater than four it's going to say you are tall enough and then there's a fallback if you don't meet either of the
previous conditions where else happens and then it's going to return saying you are not tall enough. So in these cases we are checking for if the number height
is greater than six or four. But there's
other operators we can use. We can use a three equal signs for equal to, exclamation point, two equal signs for not equal to, and then less than, greater than. And then if you want to
greater than. And then if you want to check for less than or equal to, or greater than or equal to, you can do those as well, which can come in handy if you want to make sure if it's, you know, the same as what your condition
is. All right, let's check out the
is. All right, let's check out the assignment here. So fix the bug on line
assignment here. So fix the bug on line 12. So what we want to happen is if
12. So what we want to happen is if message len is less than or equal to max message len and the program will say message sent otherwise it'll say message
not sent. So we want to say message sent
not sent. So we want to say message sent if the message length is less than max message length. So right now if we look
message length. So right now if we look at the code as is the message length is 10 and the max message length is 20. So
according to the instructions here we should get the message saying message sent. But let's run the code and see
sent. But let's run the code and see what happens. All right. So it says
what happens. All right. So it says trying to send a message of length 10 and a max of 20. Message not sent. So
this is not what should happen because 10 was less than or equal to 20. So
here's the code that we need to fix on line 12. So inside this condition, it
line 12. So inside this condition, it says if message len is greater than max message len message sent is a message that returns. Otherwise, it'll say
that returns. Otherwise, it'll say message not sent. So, this seems to be backwards. Instead of greater than, it
backwards. Instead of greater than, it should be less than. So, if message length is less than max length, then we should get the message sent. So, let's
try that again. All right. So, now it says message sent, which looks pretty good to me. Oh, sorry. Actually, if the message length is less than or equal to,
so less than or equal to, I missed that part. So, now let's test if it is equal.
part. So, now let's test if it is equal.
So, we're going to say message length is now 20 to be equal to max message length.
And it still gets sent, which is correct. Now, let's make it greater than
correct. Now, let's make it greater than the max message length. So, we'll just do 21.
And then, if we run message not sent.
So, this seems to be what we want. And
let me just change this back to 10.
So, I think we're good here with our conditional statement. So, let's submit.
conditional statement. So, let's submit.
And there we go. So, in the previous lesson, we were working with the less than and greater than operators as well as the ones using equal signs. And those
work pretty much the same way as other programming languages. However,
programming languages. However, JavaScript gets pretty quirky when it comes to the equality operators. And you
might have noticed in the previous lesson, there was a three equal sign operator for equality. So, in
JavaScript, there's actually a strict and then a not strict or more flexible one. So the strict equality is three
one. So the strict equality is three equal signs to test for equal to and then inequality exclamation point with two equal signs and then you have the
normal with two equal signs equality and then inequality and those are different. So with the strict ones it's actually going to check and make sure the types are the same. So
in this first example we're checking you know is number five equal to number six that's false. Is number five not equal
that's false. Is number five not equal to six? that's uh true. But in here with
to six? that's uh true. But in here with the two equal sign operators, it's a little bit weird. You know, five is equal to six. That's false. However,
five, number five, is it equal to a string of the number five? That will
return true, which is not what you might expect. And in the same way, the
expect. And in the same way, the inequality operator is five the number not equal to a string of the number five. This is going to return false,
five. This is going to return false, which is not what we would expect. So
this is just another quirk that comes with working with JavaScript.
So most people recommend stick with the strict equality operators. So stick with the three equal signs and then the exclamation point to equal signs when you're using these conditionals. Okay.
So in the assignment, change the operators and only the operators in the code so that each statement evaluates to true if it does not already. So let's
check. We're going to run the code as it is. All right. So the first one is
is. All right. So the first one is false. Five is greater than six. That
false. Five is greater than six. That
makes sense. And then five is equal to six. False. Five is equal to string
six. False. Five is equal to string five. False. Six is greater than or
five. False. Six is greater than or equal to six. True. Okay. So the last one is fine because it's returning true.
So the first one five is not greater than six. Five is less than six.
than six. Five is less than six.
And then five is equal to six. Let's
change that to say not equal using the strict inequality operator. And then
five is strict equal to string five. We
want to change that to use the more flexible one. So let's try running
flexible one. So let's try running again.
And now we're all returning true, which is good. So yeah, I think we're pretty
is good. So yeah, I think we're pretty good for this one.
All right. So with logical operators you can use and or and not to check whether some combination of multiple conditions is being met or not depending on what
you're looking for. So in JavaScript the and operator is the double amperand. The
or operator is double I guess pipe is what it's called and then not is the exclamation point. So we kind of saw
exclamation point. So we kind of saw that earlier with the not equal to operator. So see here true and true will
operator. So see here true and true will return true. True and false will return
return true. True and false will return false because both of those are not being met. And then true or false, it's
being met. And then true or false, it's going to be true. False or false will be false. And then not false is true. And
false. And then not false is true. And
then not true is false. So let's check out this assignment here. Textio needs
to determine whether an SMS campaign is considered high engagement. So the high engagement campaign will meet all these following criteria. So it has a high
following criteria. So it has a high open rate, which is this variable here.
And then it is a recent campaign. It
either So this is going to be the or it either has a strong reply rate or it can be sent again. So these two either one
of those can be true to return true. And
then it is not flagged as spam. Okay. So
we want to set the is high engagement variable using the given conditions and the appropriate logical operators. And
then you can use parenthesis if you need to specify an order of operations. Okay.
So, is high engagement and we do want the high open rate to be true.
So, like that. And then and it has to be recent and either has a strong reply rate or can be
sent again. So because this is an or,
sent again. So because this is an or, we're going to add a parenthesis so we can evaluate that separately first before adding it to the amperand conditions. So either has a strong reply
conditions. So either has a strong reply rate or uh can be resent again or sent again.
Okay. And then the last one is going to be it is not flagged as spam.
There we go. Okay. So, let's just double check this. Is high engagement, has a
check this. Is high engagement, has a high open rate, and is recent, and either either one of these has a strong
reply rate, or can be sent again, and the last condition is not flagged as spam. So, this one actually want to be
spam. So, this one actually want to be not flagged as spam, the exclamation point. Okay, so let's run this and see
point. Okay, so let's run this and see what happens.
campaign is high engagement equals true.
So let's actually check the the values of these variables. So high open rate is true which is does meet the conditions is recent is true and then either has a
strong reply rate or can be sent again.
So one of these has to be true and can be resent is true which makes it pass.
And then the last one we want it to not be flagged as spam. So we do want this to be false. So that is what we have there.
and it is high engagement. So that looks pretty good to me. So I'm going to submit this. Yay. All right. So switch
submit this. Yay. All right. So switch
statements. So these are similar to if else statements, but they are, you know, a more efficient way of handling if you're checking for a variable with
multiple possible values. So if we look at the code example here, we are checking the value of the OS variable.
So if it is Linux then it's going to return the creator value as Linus Torvalds. If the OS is Windows it's
Torvalds. If the OS is Windows it's going to return Bill Gates and etc. And we could write this saying you know if OS equals Linux creator equals Linus
Torvalds if Windows if OS equals Windows if OS equals Mac etc. And it would work but it would just be a lot of like parentheses and curly brackets. So, it's
nice that we have this switch case that we can use to write the code a little bit more compact. Um, one note here, JavaScript will continue to execute the next case until it reaches a break or return statement. So, you want to make
return statement. So, you want to make sure you have a break or return statement after each case. So, you can see in each of the cases here, it ends on a break statement. So, let's check
out this assignment. So, fix the bug in the billing cost function. This one
here, the basic plan is set correctly, but we need matches for the pro and enterprise plans too. So, it looks like we are adding more cases for pro and enterprise and then test your function
with the provided cases to ensure correctness. Okay,
correctness. Okay, so let's add more cases here. So, we got case basic return 10. So, we can follow
this.
Just going to copy and paste.
So case is pro the cost should be 20 and then if the case is enter price the cost should be 50 otherwise if none of these
three meet the value it's going to return zero. Okay so it's basically
return zero. Okay so it's basically returning the cost for all the different plans. So let's run this. So cost for
plans. So let's run this. So cost for basic plan is 10 which seems right. Cost
for a pro plan is 20. Cost for an enterprise plan is 50. and then free planet zero and unknown planet zero because they are this default case here.
So I think that's right. So let's submit this and see if it works. Yay.
Nice. So the turnary operator this is another way that we can write if else statements just using a more compact way of writing it keeping everything into
one line on a single expression. So the
way the syntax works is in this example we are going to determine the value of the price variable and the way it's going to be determined is we're going to
check if this is member variable is true or false. So this is kind of why the
or false. So this is kind of why the question marks here. So it's like is member true. If it is true then in the
member true. If it is true then in the first slot here it's going to set it to $2. And then after the colon, if it's
$2. And then after the colon, if it's not true, if it's false, we're going to set price to be $10. So, this is
basically the exact same thing as using the standard um if else syntax where we declare our price variable, then using an if statement, we're checking the
value of the is member boolean variable, and then if it is true, we'll set the price to $2. Otherwise, we'll set the price to $10. So you can kind of see when you compare these two versions that
you know it's a lot more compact having everything on one line. I would just use this for kind of more simple conditions.
Once things get really complex then it can get a little bit confusing if you're trying to do this turnary thing. So it's
good for simple conditions. So with all that in mind let's check out the assignment here. So in the assignment on
assignment here. So in the assignment on line six, create a variable called message status. And then we want to use
message status. And then we want to use a turnary operator to set the value of the message status to either processing or failed. And then it's going to say
or failed. And then it's going to say processing if the number of retries is less than the limit. And then once the number of retries is equal to or greater
than the limit, then it's going to say failed. So let's start writing this code
failed. So let's start writing this code here. So we're going to say let
here. So we're going to say let message status be set to the number of retries
num retries is less than the limit. So if this is true, if the number of retries is less than the limit, so it hasn't surpassed the limit, then we will return
still processing.
Otherwise with the colon we're going to return failed.
Okay. So let's just kind of double check. So for processing the number of
check. So for processing the number of retries is less than the limit which is what we added here. And then otherwise if retry if number retries is equal to
retry limit or greater than it's going to say failed. So this should work. So
let's run the code. It says processing and that is because the number of retries is nine and the retry limit is 10. So it is less than the limit. Now
10. So it is less than the limit. Now
let's check if the number of retries is equal to the limit. So according to the instructions here, this should return
failed if it is equal. So run and it's failed. Now let's also check if the
failed. Now let's also check if the retries is greater than the limit.
It should also say failed. Okay, looks
good. And we want to change this back to nine.
And yeah, processing. So, this should be good to submit.
All right. Awesome. Okay. So, like I said previously, I would use turnary operators for sort of simple conditions that aren't overly complex. And this
kind of shows you why. So here is an example of a creative way of writing a condition. So here we are setting the
condition. So here we are setting the value of vehicle name and we are checking first we're checking if it is a truck. If it is a truck then we'll say
truck. If it is a truck then we'll say truck. If it's not a truck then we're
truck. If it's not a truck then we're kind of nesting another condition in here. If it's a car we'll return car. If
here. If it's a car we'll return car. If
it's not a car if it is a scooter then we'll return scooter. And then if it's none of those things, it's going to return vehicle. And
return vehicle. And this does work logically, but if you kind of read that, it is very hard to parse as a human, not a computer. So you
can write this same statement using a regular if else statement. You can see this is a lot easier to read. It's
easier to sort of quickly identify. You
have three conditions. If it's a truck, if it's a car, if it's a scooter, otherwise it's going to be vehicle by default. And then there's another way
default. And then there's another way you can write this using a function get vehicle name. And then you have these
vehicle name. And then you have these different condition values here. So
again, this is still I would say pretty readable like the if else statement compared to, you know, whatever this is.
So yeah, ultimately code is written for humans, not machines. And I've sort of seen some people, they're trying to save lines of code and just make things as compact as possible by using a ton of
turnary statements. And that's fine. But
turnary statements. And that's fine. But
whenever you write code, you have to remember that you know you in the future or another developer programmer might be going back to this code and the longer it takes to parse and understand the
existing code, the longer it's going to take to make whatever fixes that you have to make. So, you know, in a lot of cases, I think it's better to have more
lines of code in order for it to be more understandable for humans in the future, whether that's yourself or somebody else. Okay. So with that in mind, he we
else. Okay. So with that in mind, he we have a little quiz here. Use turnaries
when the logic is simple. Yeah. All
right. Truthy and falsy. So we worked with true and false using booleans in conditions before. But in addition to
conditions before. But in addition to the you know explicitly true and false values, there's other values that might return true or false depending on what they are. So check out this example
they are. So check out this example here. So in this first condition, we are
here. So in this first condition, we are checking whether the string hello is true or false. And this is going to return true. Hello is truthy. Same thing
return true. Hello is truthy. Same thing
for this number 42. It's going to return true. 42 is truthy. So that might sound
true. 42 is truthy. So that might sound kind of confusing, but let's check out this next example. A falsy value works the same way, but for values that evaluate to false. So these are values
that aren't explicitly you know false but they are considered false or falsy.
So one of them is zero. The number zero is considered falsy. In addition to zero, null and undefined are also considered falsy values. And we can read
more of these here. So truthy values are true a number a string a number that's not zero a string. And then empty array object and functions. and then falsy
values are, you know, false, zero, an empty string, null, undefined, and then not a number. So, let's check out this assignment. There is an issue with how
assignment. There is an issue with how Texio checks the number of user credits before sending a message. Some users
that have negative credits are still able to send messages. So, user needs to have at least one credit to be able to send a message. So, they can't have zero
or negative credits in order to send a message. fix a bug on line five to
message. fix a bug on line five to correctly check whether the user has enough credits. So user credits is set
enough credits. So user credits is set to -2. So right now we have this
to -2. So right now we have this condition saying if user credits is true, it's going to say sending message otherwise it'll say not enough credits.
So because it's -2, it's not zero. So
this will return true even though it's a negative number. Um that's just kind of
negative number. Um that's just kind of how the the truthiness works. So when we run the existing code without making any changes, it's going to say sending message. So what we want to do is we
message. So what we want to do is we want to check whether the user credits are greater than zero. So it means it
has to be not zero but one or more. So
if user credits is greater than zero.
Now let's click run again. Not enough
credits. All right. So that should be good.
And we are at the last lesson of chapter 2. So this is about nullish coalesing.
2. So this is about nullish coalesing.
And I know those sound like fancy words, but here's what it means. So it helps you determine what to do if the value of
a variable is null or undefined. And the
nullish coalesing operator is the double question mark. So this lets you set the
question mark. So this lets you set the value of a variable to be some default value if it happens to be null or undefined. Otherwise, it'll return the
undefined. Otherwise, it'll return the value of the variable if it's not null or undefined. So here's what that looks
or undefined. So here's what that looks like. So in this code example, we are
like. So in this code example, we are going to check the value of the my name variable and we've explicitly set it to null. So in this condition, if my name
null. So in this condition, if my name is null, it's going to return the value of anonymous. Otherwise, it's going to
of anonymous. Otherwise, it's going to return the value of whatever the my name variable is. So in this first case, when
variable is. So in this first case, when my name is null, it's going to return anonymous as this default value that we set. Now if my name has a value, so if
set. Now if my name has a value, so if the value is lane, a string, then it's going to not return anonymous, but it's not null. So it's going to return the
not null. So it's going to return the value of my name, lane. So this is just a really nice concise way of handling this. So yeah, it's a it's a way to set
this. So yeah, it's a it's a way to set sane defaults for variables that might be empty. All right, so here's the
be empty. All right, so here's the assignment. Certain users in the Texio
assignment. Certain users in the Texio database do not have a subscription type. By default, customers who aren't
type. By default, customers who aren't subscribed are considered a guest. So we
want to use a null coalesing operator to fix a code that starts on line 9. So
that an empty subscription type defaults to guest. So up at the top we have some
to guest. So up at the top we have some variables for the customer information.
James Holden AT&T phone number and then the subscription type has been set to null. So this person is not subscribed.
null. So this person is not subscribed.
And then we are going to log a statement saying creating subscription type profile for name with provider at phone number. So let's just run the existing
number. So let's just run the existing code. So it says creating null profile
code. So it says creating null profile for James Holden with AT&T at this phone number. And instead of null, we want it
number. And instead of null, we want it to say guest. So what we can do is in the console log function, I think if subscription type is null, double
question mark, we want to return a string saying guest. So now let's run this again.
So now it's saying creating guest profile for James Holden. And just to test this code even more, it says don't touch above this line, but we'll change it back. We're going to say subscription
it back. We're going to say subscription type instead of null, we'll say basic on the basic plan. So now it says creating basic profile. So I think our code does
basic profile. So I think our code does work. So let's put it back to how it
work. So let's put it back to how it was. And I think we are good here. So
was. And I think we are good here. So
let's submit this.
And there we go.
All right, so we're on to chapter three and this chapter is all about functions.
So let's take a look at how JavaScript deals with functions. All right, so to declare or create a function, you write out the function keyword, the name of the function, and then if you have any
parameters, you can put those in there, and then any code will go inside curly brackets. All right. Then to call or
brackets. All right. Then to call or execute the function, you can declare a variable like result. Run the function and then you can put in any values of
parameters, you know, if it has it. And
then here's the result value. So in this assignment, we need to manipulate strings in textio.
We're going to use the concat function concatenate to take two strings and combine them together. So hello plus world will give you hello world. So we
need to fix the function signature of concat to reflect the behavior that we want it to have. So let's take a look at the function here. So here's our concat function. We want it to return string
function. We want it to return string one concatenated with string two and then don't touch below this line. So
let's just run the code initially just to see what we get. So string one's not defined because we're returning these two strings but we haven't actually
declared them. So if you look up the
declared them. So if you look up the example up above, you can sort of copy that same pattern. So string one, string two. So we separate the
string two. So we separate the parameters with commas. So now let's try to run again.
All right, looks like the messages are good. They are concatenating the two
good. They are concatenating the two strings in the parameters.
So I think this is good to go.
Nice. And up next we are looking at function hoisting. So in Python as well
function hoisting. So in Python as well as other programming languages you have to define or declare a function before you actually execute it. But in
JavaScript you don't have to do that. So
in JavaScript you can call a function before you actually declare it in your code. So I think this is just another
code. So I think this is just another example of how JavaScript is very flexible. Sometimes in good ways and
flexible. Sometimes in good ways and sometimes in not so good ways. And the
reason this works is because JavaScript does something called hoisting the function declaration as well as other declarations to the top of the file before the code's executed. So feel like
hoisting is a funny word. It reminds me of like pirates like hoist the sales.
All right, so let's look at this quiz here. Functions need to be defined
here. Functions need to be defined before they are called. This is false in JavaScript.
So another question. JavaScript engines
execute code from start to finish without looking ahead. This is false.
Nice. And next up, we're looking at unit tests. So, this is going to deal with
tests. So, this is going to deal with how we're submitting our code as we continue progressing through the course.
So, before we would submit our JavaScript code, and it would check the output. Now, we're going to be doing
output. Now, we're going to be doing unit tests. So, we have another
unit tests. So, we have another JavaScript file here in the second tab.
This is going to do the test and it's going to actually check the the value that we're returning and making sure it matches what the right answer is. And
the reason that we're doing this is that it is more real world. So in the real world there's unit tests. So it's good to get used to them now. And it also benefits us because we can write a bunch
of console log statements to you know test our code as we're going and we can leave them in. We don't need to worry about removing them at the end. So let's
check out this assignment. Complete the
get monthly price function. So it
accepts a tier string as input and then it's going to return the monthly price for that tier in pennies. And the reason we're doing pennies as opposed to dollars is because we want to avoid
floatingoint errors because you know when you're doing math some decimals don't have like a small number of decimal places. They have like super
decimal places. They have like super long or even like infinite places. So
it's kind of best to just have everything in pennies and we can do the math from there to convert it into dollars if we need to. All right. So
here is the function get monthly price.
So we have three different tiers with three different values. So this tells me that maybe we want to write a switch case kind of thing. So
switch and what is switching meaning what are we get having different values for it's the tier and
in the first case it's going to be basic and then if it's basic we want to return we need to convert the price from
dollars to pennies. So $100 um $1 is 100 pennies. So 100 plus another 100.
pennies. So 100 plus another 100.
Okay.
Second case premium and that's going to be 150 that we want to return.
and then third case enterprise and we're returning 500 with another 100. Okay, so we've written the
another 100. Okay, so we've written the code. Now let's test the code. So I'm
code. Now let's test the code. So I'm
going to call the function in a console log. So get monthly price and let's say basic.
So, what we are hoping will happen is is it's going to return the 10,000 number for basic.
Cool. So, I think that's right. Let me
just double check the instructions. We
want to yeah return the monthly price for that tier in pennies.
So, that looks good to me. So, we are going to leave in that console log statement because we can.
Um, oh, and then actually it failed. Should
return zero if it's empty. I forgot
about that. Yeah, if the given tier doesn't match any of the above, return zero pennies. So, default
zero pennies. So, default is I think what we wanted return zero.
So, let's run it again.
Cool. So, it looks like it's working. I
didn't fail. Okay, let's give this a shot. We're going to submit it. Woohoo.
shot. We're going to submit it. Woohoo.
Okay. So, next up, we're looking at multiple return values. So, in Python, as well as other programming languages, you can actually return multiple values from a function. So, we're returning
email, age, and status, and they all are working. Um, however, we can't do this
working. Um, however, we can't do this in JavaScript. In JavaScript, if you try
in JavaScript. In JavaScript, if you try to return multiple values, it's only going to return the last one active, and it's not going to throw any kind of error. So it's just kind of silently not
error. So it's just kind of silently not working. So yeah, you can only return
working. So yeah, you can only return one value from a function in JavaScript.
And to get around this, most developers return an object, which we'll look into later. In the meantime, let's check out
later. In the meantime, let's check out this assignment. So we have a profanity
this assignment. So we have a profanity detector with this function is clean.
It starts off being set to true, but if the review includes any of the following curse words, dang, shoot, or heck, it's going to change to false. And then right
now it is returning clean. and then
review. So, as we just read, JavaScript's only going to return the last value. So, let's run this code and
last value. So, let's run this code and see what comes up by default. So, yeah,
fail should return false for our living as a best dang tour. Um,
yeah. Okay. So, I think what we want to do is we want to only return the clean
value. So, let's try running that again.
value. So, let's try running that again.
And looks like we pass.
And all right, let's uh submit our code.
Oh yeah. All right. So next we're looking at functions as values. So when
it says JavaScript supports first class and higher order functions, what this really means is that anything that you can do to a variable, you can do to a function. So for example, previously we
function. So for example, previously we created a variable and we set the value of that variable to be a function. And
another thing you can do with functions is you can actually set a parameter of a function to be another function in addition to you know any other variables that you might need. So we're going to
be looking at that in this lesson. So to
start off we have these two functions add and multiply and they do the math that you might think they do based on the name. And then we have another
the name. And then we have another function called an aggregate function.
And you can see in the parameters we have a, b, and c which are going to be kind of regular variables. I'm assuming
numbers. And then we have this arithmetic function as the last variable. So what this means is that
variable. So what this means is that this function can be any function that you want it to be. So what it does in the aggregate function is it's going to do the arithmetic function with the first two variables and then it's going
to run the arithmetic function again using the result of the first um arithmetic function and then it's going to do it again to the third variable and
then it's going to return that.
So you're basically running whatever um function is in the parameter two times and then returning the result after the second time. So what this means is that
second time. So what this means is that we can run this aggregate function in order to do math using any number we want and any function that we want. So
we can run this with the addition function. We can run this with the
function. We can run this with the multiply function and it's just like a more sort of efficient way of being able to have versatile you know functions as well as variables in your parameters. So
we want to complete the reformat function which is here. It takes a message string and a formatter function as an input. Then we want to apply the
given formatter three times to the message. Then we add a prefix of textio
message. Then we add a prefix of textio and then return the final string.
So for example, if the message is general Kenobi and the formatter adds a period, it's going to add three periods to the end of that. All right. So let's
start off with this. So we can use the example here kind of as a pattern to follow.
So we want to run whatever the formatter function is three times. So we're going to do the same thing. So we're going to create a constant first result and the first result is
going to be running the function formatter and the parameter is going to be our message.
Then we want to run it a second time. So
again kind of following this pattern here. Second result is going to be
here. Second result is going to be running the formatter function. Um, but
instead of message, we want the first result to be the parameter here. And
then we're going to run it a third time.
So we'll do the same thing. Formatter.
And then it's going to run with second result as a parameter. And then we want to return the result with a prefix of
textio. So I guess we could do return.
textio. So I guess we could do return.
We can probably do a template literal here. So back tick and then we're going
here. So back tick and then we're going to say text you with a space. And then we want to load
the third result. So dollar sign set of curly brackets and then third result.
Cool. So let's run this and see how it looks. Okay, this looks pretty good.
looks. Okay, this looks pretty good.
Yeah. So let's give it a shot and submit this.
All right. Nice. And we are now on to scope. So we did talk about scope
scope. So we did talk about scope earlier with variables when we were talking about how the old way of declaring variables with far has a function scope versus the new way of
declaring variables with let and const have a block scope. So this is kind of going through a little expanded on that idea and going through the different levels of scope from biggest to smallest
or highest to lowest. So the biggest scope is the global scope. So everywhere
if you have a variable that is declared in the global scope, it's available globally from anywhere in your codebase.
And this can be good, but it can also be bad. And for that reason, I think we
bad. And for that reason, I think we have sort of smaller scopes in order to introduce a bit more level of control and just to make sure that unexpected things don't happen um with your
variable values. So in browsers um
variable values. So in browsers um global variables are part of the window object. in node they are part of the
object. in node they are part of the global object. So working down our way
global object. So working down our way through the levels the next one which is a bit smaller than global is the module scope. So just really broadly speaking
scope. So just really broadly speaking instead of having you know one giant code base you can break down your code into smaller pieces called modules. So
if you declare a variable at the top level of your module it's going to be scoped just to that module and it's not going to be globally available. And then
this is what we were kind of covering earlier with our variables. So var
variables the older ones are scoped to a function. So they're accessible within
function. So they're accessible within that function and then any nested functions. And then the smallest scope
functions. And then the smallest scope that we have here is the block scope. So
with let and const the block which is you know whatever code is inside curly braces that's where the scope is. So
even within a function it has to be within the right block in order to be accessible. So basically this smaller
accessible. So basically this smaller scope makes the variables more predictable reducing the chances of accidental variable hoisting which we talked about earlier. All right. So
let's check out this assignment. Okay.
We have come across a bug involving scope issues in the textio codebase. So
the function get message status returns the status of a message based on its length and it has a nested helper function is valid length to check if the message has more than zero characters.
So fix get message status that it uses the result of is valid length which is this helper function in here to set the message status. Okay. So let's take a
message status. Okay. So let's take a look at what the function is kind of initially. So here's the get message
initially. So here's the get message status function and it initially has a value of message status as processing. So this is the
default value and then inside it is another function is valid length and it's going to take the parameter from
the original get message status function as its own parameter and then it's going to have message status initially be set
to invalid but it'll change to valid if the message length is greater than zero and then it's going to return message status.
So then after the end of the is valid length function which is here there's some more code where it's running the is valid length message.
It's calling it with the message parameter and then returning message status. Okay. So that is the function.
status. Okay. So that is the function.
Let's run it and see what happens with just the default code that we have right now. All right. So as we sort of
now. All right. So as we sort of suspected it's going to fail initially because we haven't made any changes to the program. So it's saying that it's
the program. So it's saying that it's returning processing instead of valid for the first two cases and then it's returning processing instead of invalid.
So basically it's not correctly running the is valid length code. So let's take a look at this. So it's returning processing when it shouldn't. So this is
the initial value here and then message status gets changed inside the is valid length function. However, as we talked
length function. However, as we talked about just before, the let variable is has a block scope. So that means that when it's changing the value of message
status, it's only going to be affected inside this this block here. So what's
happening is it's running is valid length with the message parameter but then it's returning message status and the message status is getting changed
inside the is valid length which is a function scope not a block. So within
this block we need to find where message status is getting set and that's not going to be inside the function but it's going to be in this main block of get message status which is processing. So
that's kind of why we're returning processing versus invalid or valid when we don't want that to happen. So we want
the message status to return you know the change value from is valid length and we can only change the code down here. So instead of returning the
down here. So instead of returning the message status from the you know the block that it's in right now I think we want to return the function
is valid length with the message parameter that we have from get message status. So we're returning the value of
status. So we're returning the value of this function. So this is going to run
this function. So this is going to run this function and then return the proper message status. So I think this should
message status. So I think this should work. So let's run.
work. So let's run.
Hey, there we go. Yeah. Yeah. So, it's
returning valid, valid, and then invalid for the message that has zero characters. So, this should be good.
characters. So, this should be good.
Nice. Okay. So, we're on to lesson eight. Anonymous functions. So,
eight. Anonymous functions. So,
anonymous functions have no name, hence the name anonymous. They're useful when defining a function that you only just need to use once or if you want to create a quick closure. And from what I understand, a closure is a function
defined inside another function. So,
let's take a look at how this works.
So right now we have a function called conversions and conversions takes four parameters. It takes a function called
parameters. It takes a function called converter and then three additional parameters.
And inside the conversions function it's going to run that converter function with each of the three parameters and then it's going to set them as variables and then it's going to log those
variables. Now if we want to use a
variables. Now if we want to use a conversions function using a named function so not an anonymous function what we can do is we're running the conversions function here and the
parameter the first parameter is going to be this double function and we have defined this double function sort of external to the conversions function and
then it's going to return the doubled value of the parameter. Then we can run the double function with each of the three um parameters there. Now, if you
want to do this with a an anonymous function, it's similar except inside the conversions when you're calling the conversions function, instead of this
named function double, we're instead going to have an anonymous function which has the same functionality as the double function up here where it's a plus a and then it has the three
remaining parameters and it will basically do the exact same thing as the first example up here. All
right. So, let's check out the assignment. So, we want to complete the
assignment. So, we want to complete the print report function, which is this thing here. It takes a sequence of
thing here. It takes a sequence of messages, intro, body, and outro. So,
these are going to be the three parameters.
And then for each of those three, it should call print cost report once in order. And the print cost report is this
order. And the print cost report is this function here.
And it takes two parameters, cost calculator, a function, and then the actual message. And then it's going to
actual message. And then it's going to calculate the cost of your message.
And then at the bottom, we're running print reports with these three messages, intro, body, and outro. Okay. So inside
print reports, first thing it says was it should call print cost report once for each message. So print cost report.
And let's just do calling the intro first and make sure we get that correct.
So print cost report is going to take two parameters. The first one's going to
two parameters. The first one's going to be the function. And we were told to use an anonymous function. So function
I'll just do a right now. And then
that's the first parameter. And then we have the second parameter which is the message. And for intro,
message. And for intro, I'm assuming this should be the intro message.
Okay. So now we need to calculate the cost of the intro message.
So if we look farther down, the cost for each type of message is calculated.
Intro is 2x the message length. And then
we can use the built-in length property.
Let's try return. I think we want to
return. I think we want to maybe return intro. So maybe intro should be the parameter here.
So intro is going to be the actual message and we want to get the length of that message and then we want to multiply it by two I believe and then intro is going to be the second
parameter. So we have our first
parameter. So we have our first parameter the anonymous function and then we have the second parameter which is the message itself. So
let's just run this and see what happens. Okay, so we have run print cost
happens. Okay, so we have run print cost report using the intro message. Welcome
to the hotel California.
And then has a message and then it's telling us the cost which is 62 cents. So I mean that seems it seems like it would be I
think a right number. Um, I guess just for testing purposes, we can just replace this temporarily with hello because we know that's five.
So yeah, so 5 * 2 is 10. So that seems correct mathwise. So we'll put that
correct mathwise. So we'll put that back. Okay, so I think our functionality
back. Okay, so I think our functionality works. So I guess we'll just duplicate
works. So I guess we'll just duplicate this twice. So the next one's going to
this twice. So the next one's going to be for a body. And am I confident about this code? Not super confident, but
this code? Not super confident, but let's see.
Outro is the last one. And then we need to update the math. So body is going to be 3x and then outro is 4x.
Okay. So let's run what we got.
Um, and that seems correct. 62 cents. The second one is 3x.
correct. 62 cents. The second one is 3x.
It's 57 cents. So, it's about the same, but it's fewer characters. So, that's
probably correct. And then the last one is longer and it's also more expensive.
So, that seems roughly okay. All right.
So, let's just submit and see what happens.
Okay. Nice. Okay. Default parameters.
So, we were working with parameters and functions in the previous lesson. In
this one, we're looking at default values that you can set for optional parameters in case it's not set when the function is called. So in this example
here, slide this over, we have a get greeting function and it has two parameters, email and name. And then
name has a default value, the string there if it is not set. So then it's going to log a string saying hello name, welcome, you've registered your email
email and then we can see two different examples of calling this function. So in
the first example we have a name lane and it returns hello lane welcome you've registered your email lane example.com.
Then the second example there's no name parameter set. So it's going to default
parameter set. So it's going to default to that there value. So it's going to return hello there instead of the name.
And then the rest of the message is going to be the same as it is before. So
we need to complete the create contact function which is this one here. And it
should take three parameters. Phone
number, name, and avatar. And it looks like name and avatar are optional. So if
you don't set name, it's going to default to anonymous. If you don't set an avatar, um I'm assuming it's going to be like a file name of an image file, then it's going to default to
default.jpeg.
default.jpeg.
And here's some further instructions. If
a phone number is not passed, it should return the string invalid phone number.
So this is a mandatory parameter. It's
not optional. And then otherwise, so if there is a phone number, we want to create a new string concatenating the given avatar file name to the string
public/ pictures and then return a string saying contact save name colon name phone number col number avatar
colon file avatar file path which is going to be this thing with the public and pictures path.
Okay, so we're actually writing a lot of code in this um in this function.
So let's start by adding the three parameters. So in create contact phone
parameters. So in create contact phone number, name that's going to have a default value of anonymous
and then avatar with a default value of default.jpeg.
default.jpeg.
So that seems pretty good.
Now the phone number is mandatory. So if
there is no phone number, we want to return a string saying invalid phone number. So I think just for testing
number. So I think just for testing purposes, I'm going to run this function as is. And it obviously shouldn't pass.
as is. And it obviously shouldn't pass.
So let's see here.
So the first test fails. It should
return contact saved name yada yada expected undefined equal contact saved.
Okay, so there's really not anything going on yet. So I think the first thing we need
yet. So I think the first thing we need to write is maybe an if condition. So if
the phone number is not passed.
So if phone number and then if it's not passed, I don't know if it's like going to be undefined
or null or something else. Let's try if it's not undefined.
I don't know if this is cheating. Let's
check out the uh the test code here. So
in the first example, the phone number has a value of a string. The name's
given and then there's no avatar. It has a default. In the second one, there's a
default. In the second one, there's a phone number, there's an avatar, and then there's no name, so it'll be anonymous.
And the third one, there's no phone number. So this looks like an empty
number. So this looks like an empty string.
And then there's a name and an avatar.
So I guess we'll just follow that format undefined.
Okay. So I don't think this will change anything if we run this as is.
Yeah. So actually phone number is not equal to empty. Then we'll do code, you know, we'll run other code and then
we'll do an else statement here and then it should return the invalid phone number string.
Okay, let's try running this.
Okay, so the third test case passed because we did sort of handle what happens when the phone number is empty.
So that seems good, I think. So now
let's take care of the other cases where we have a phone number and we may or may not have the name or the avatar. So if
we have the phone number, I think we can just return that string. I want to use a template
that string. I want to use a template literal. So, let's just copy this. And,
literal. So, let's just copy this. And,
you know, we'll want to do this, I believe. Um, name
and then phone number.
And then for the avatar, we want to do the file path thing. So maybe I will declare. So we'll say let I guess it's
declare. So we'll say let I guess it's not going to change. So I guess there's no harm in doing const file path.
const file path equals avatar and what was it? Oh, we want to do this string here.
So let's copy that and this. And then I guess it doesn't
and this. And then I guess it doesn't matter too much. We'll just concatenate it with that plus sign. Okay. So, we
have the file path here. So, now instead of this avatar file path, we'll load the actual file path.
Okay. Just going to maximize this. Let's
just look this over.
So, phone number is not empty. We're
going to create file path with the path and the avatar. um which we do have a default for and then we will return
forgot a semicolon there. Um we will return contact save name and loads a name phone number loads a phone number
and then avatar is the file path. Okay, so I think this may work hopefully. Let's run it and see. Okay, cool. So looks like they all
see. Okay, cool. So looks like they all passed. So, let's give this a shot.
passed. So, let's give this a shot.
Yay.
Just out of curiosity, I'm just going to look at the solution here.
Um, I guess I could not make my lines as long by like following this thing here.
Um, phone number, name, avatar.
Okay. And then I did not do this. So if
phone number Oh yeah. So I think
Oh yeah. So I think phone number is empty it'll return false.
So maybe that's what this means. And
then yeah the other code looks like it's pretty similar. All right. Lesson 10.
pretty similar. All right. Lesson 10.
Passing by value.
So this is saying that um pass by value means that when a variable is passed into a function um as a parameter that function is going to receive a copy of the variable the function can't mutate
or change the original data which you know that makes sense. So in this example here we have this variable x= 5
and then we are incrementing it. So with
the increment function it's going to increment by one and then under that we are logging the value of x. So in this one even though
we're executing the increment function with the value of five inside the function um it does change it increments
by one to six but this six value is only going to exist inside this function here. So outside the function, you know,
here. So outside the function, you know, doesn't have any effect. I can't change the value of five to six here. So this
is why it's still going to be five down here. So basically, you know, a function
here. So basically, you know, a function can't affect values of parameters outside of the function itself. Okay. So
fix the bugs in the monthly bill increase here in the get bill for month functions.
So monthly bill increase, we're returning the increase in the bill from the previous to the current month. And
then if it decreased, it's going to be a negative number. And then get bill for
negative number. And then get bill for month will return the bill, which I'm assuming is going to be some kind of dollar amount equal to the cost per send
times the number of messages sent. So
that's going to result in the final bill for that month.
And then it says, "Looks like whoever wrote the get bill per month thought they could pass in the bill parameter, update it inside the function inside this function here, I'm assuming." And
then the update would apply in the parent function here, but they were wrong. So we want to change the get bill
wrong. So we want to change the get bill for a month function to explicitly return the bill for the given month. And
be sure to capture that return value properly in the monthly bill increase function.
So the function signature for get bill for month should only take two parameters when you're done. So we need to change this function to explicitly return the bill for that given month.
So yes, this function is not returning anything.
So I think what we might want to do is okay. So I think yeah, we don't need
okay. So I think yeah, we don't need this bill parameter cuz all we need is a cost per send and then messages sent.
And then instead of setting bill to be that, we're going to return
cost percent times messages sent. Okay,
so I think that looks better. So let's
just kind of eyeball. So monthly bill increase. We're initializing the last
increase. We're initializing the last month's bill and then this month's bill.
And then it's going to run get bill for month for the last month's bill. And
then it's calling get bill for month again for this month bill and because I'm not sure this is going to work.
I'm not sure this is going to work because get bill for month needs to I removed the two parameters. So it's only for cost per percent and messages sent
but it has to be associated with the specific month. So we need to change
specific month. So we need to change these function calls to have two parameters to match you know the actual
function. So cost percent
function. So cost percent that's the same. So I think that's fine.
But then messages sent up here that will be numb last month and then numb this month
and then we should be able to remove the this month bill.
And I feel like we actually need to set the value of these variables to be this function. So get bill for last month.
function. So get bill for last month.
I'm going to move that there. And then
get bill for this month.
Paste that in. So that seems more right, I think. Let's run this and see how the
I think. Let's run this and see how the tests go.
Okay, looks like maybe we're good. Yeah, these three tests did
we're good. Yeah, these three tests did pass.
So, okay. Yeah. All right, let's try it.
Woohoo. All right. So, we have arrived at the last lesson in chapter 3. This is
called immediate invocation.
Sounds like a spell thing. All right.
All right. So you can immediately invoke a function after defining it using the not at all hard to pronounce acronym I if or if perhaps immediately invoke
function expression. So let's look at
function expression. So let's look at what this looks like.
So this looks like the function an anonymous function and then it's immediately getting run and this one doesn't have any parameters. So
it's like there's no values in there.
And then the example below, we're declaring this result variable and we're setting it to be running this
function with these two parameters. So
it's going to return a + b which is three.
So like a better name for this would be anonymous autonomous functions because they run themselves.
But I'm not a programming expert. So I
don't think I have the power to name things. Okay. So it looks nasty, which
things. Okay. So it looks nasty, which it does. It does look a little bit much,
it does. It does look a little bit much, but it's occasionally useful. It has its own scope. It can be convenient for
own scope. It can be convenient for computing a value like a single expression like running the setting the function to be the value of uh a variable. And then there is some async
variable. And then there is some async functionality which we will get to later.
All right, here's the assignment. Run
the given code. Notice that the total variable doesn't store the resulting number, but it's actually a function.
All right, let's try this out. So, I'm
going to run it.
And yes, it is logging the total, but that total is not, you know, the the result of the function, but it's actually literally returning,
you know, function calculate total, etc. So, we want to turn this into an if or an anonymous autonomous function.
So let's look at the oh and then we want to run it with number of messages is 100 and then bytes per message is 24.
Okay. So anonymous we want to not have a name here. And then I believe we wanted
name here. And then I believe we wanted to wrap it in parenthesis like that.
So it kind of encapsulates it and then the parameter values go in there.
So the first parameter is numbum messages which is 100. Oops that was wrong. There we go. Which is 100.
wrong. There we go. Which is 100.
And then bytes per message is 24.
24. Okay. So I think that's right. Let's
just run it and see what happens.
Okay. Total message cost 2400.
That seems like good math. So yeah, I think that should be good.
All right, we're going to submit.
Nice.
All right, so I think that's it for uh chapter three. Good job, everybody.
chapter three. Good job, everybody.
And we are on to chapter 4, objects. So
my guess is that in this chapter, we are definitely going to start hitting topics and concepts that I'm not super familiar with, just cuz, you know, I didn't learn a lot of this stuff formally. So, you
know, we'll see how that goes. It should
be interesting. And you know, at the very least, I'll get to learn some new stuff, which is always fun. All right,
so let's check out this first lesson.
JavaScript objects or object literal, okay, they're used to store data in key value pairs. So that makes sense. So
value pairs. So that makes sense. So
here we're creating the variable called apple. And then the value is this set of
apple. And then the value is this set of curly brackets and then inside the curly brackets, we have three different properties. So we got name, radius, and
properties. So we got name, radius, and color. And then they're all after the
color. And then they're all after the name you have a colon and then whatever value you want for that property and then there's a comma separating them all. And then we can access them with
all. And then we can access them with the dot operator. So if we want to get the value of this name property in the apple object, we can call it by saying apple.name.
apple.name.
So that makes sense. Okay. So JavaScript
objects um are used in the same way a map or dictionary in other languages are used.
But we can also use them for more complex things like classes and prototypes which we will get into later.
All right, so here's the assignment.
Complete the create message function. It
should return a new object with the following properties. Phone number,
following properties. Phone number, message, and message length.
Okay, so let's create our const. And what do we want to call this?
const. And what do we want to call this?
I will say phone message just so we're not having the same name as there's already a message property.
Okay. So phone message and it's going to be phone number colon and the value of that is going to
be phone number and we want to end with a comma because we have some more properties. The next one is message and
properties. The next one is message and that will be the value of the message parameter
comma and then message length and that's going to be can use the length property I believe. So let's just run
this and see what happens. Okay, it
failed. Uh results undefined. I forgot
to return.
So, I think we have to actually return the phone message.
Okay. So, let's try running again. Oh,
and it looks like it passed. Okay. So, I
think I'm good to submit this. Nice.
And just out of curiosity, I'm going to click the solution and see what they have listed.
Okay, that seems pretty much the same as what I wrote. So, I think we're we're pretty good there. All right. So looks
like when we're creating these key value pairs in the object, we can create it externally from the object itself. So we can declare this
object itself. So we can declare this radius variable, set the value to two, and then inside the apple object, we're creating a property called radius and
setting the value to be the value of the radius variable.
Um, and then the same thing for color.
But we have another option which is to create the constant outside of the object. But then inside the object we
object. But then inside the object we can just say radius and then this will create a property called radius and then it's going to automatically set the
value.
So that's pretty interesting.
So we're having the key to have the same name as an existing variable. And then
this is just to kind of compare with the sort of other way of doing it.
Okay, so with that in mind, which is not the same the car key and then car value and then this is going to be the value
of I guess the externally declared property car or variable car. And the
second one is it's just setting the value of the car property to a string car, which that's probably not it. and
then car which is going to be kind of like this radius example here where it's creating a property inside the object called car and it's going to have a
value of whatever the value of the car variable is. So I think the one that's
variable is. So I think the one that's not the same is going to be this one.
Cool. Okay. So far we have learned how to create objects with properties. Now
we'll learn how to update and add properties to existing objects. So
that's pretty cool. So we got our apple object here with name, radius, and color like we had previously. But now we can create a new property called numbum
seeds. So after the object declaration,
seeds. So after the object declaration, we can just say apple.num seeds equals 3 to create a whole new property. Or we
can change an existing property, the color, by saying apple.color color
equals green. That's pretty cool. Okay,
so here's the assignment. So we're going to we need to create text campaigns with a unique ID. So in this add ID function,
it takes a campaign record object as a parameter and then returns it with a newly generated ID property. So we're
creating a new ID property in the campaign record object. Okay. And then
the ID is going to be the campaign name dash and then sender name. Let's create
our constant. This going to be the object. Actually, if this campaign
object. Actually, if this campaign record already exists, I wonder if we can just say campaign record
and then create the new property ID and then set it to be campaign name.
I'm not sure if this is going to work, but I guess we're giving it a shot. And
then sender name and then I guess return it. return
it. return campaign record.
Okay, I'm just going to give this a shot and it fails. So, let's see what happened. Campaign name is not defined.
happened. Campaign name is not defined.
Oh, I forgot to campaign name and sender name are supposed to be properties of this object. So, I forgot the campaign
this object. So, I forgot the campaign record dot thing. There we go.
Okay, let's try it again.
Hey, it passed. I'm always surprised.
Okay. So, I guess we'll just submit it.
And I am going to check the solution just because I'm kind of curious to see like what the, you know, right answer is.
And I did not use the template literal, but it still did the same thing. Okay.
So, that seems like, you know, pretty good. So, this is pretty cool. You can
good. So, this is pretty cool. You can
contain objects within other objects. So
for example, we have I guess this parent object tournament and it contains two child objects referee and prize and each of those are also objects themselves. So
it's kind of a nice way that you can organize the data inside the object. And
then we can access nested properties by chaining tournament.referee.name.
chaining tournament.referee.name.
So the name is the property of the referee object which is a property of the tournament object.
All right. So let's look at the assignment. Okay. So we have text
assignment. Okay. So we have text campaigns stored as nested objects. So
we have in the campaign object which is I'm assuming the overall object. Here we
have a creator and that's also an object and it contains the creator's name and date. Okay. So finish the get campaign
date. Okay. So finish the get campaign creator function which takes a campaign object and returns a creator's first name. Okay. So just put that over there.
name. Okay. So just put that over there.
Okay, so in the function we want to get the campaign object which is the parameter and then we want to return campaign
dot and then if this whole thing is a campaign the creator is a property in campaign. So creator dot then we want to
campaign. So creator dot then we want to return creator's first name. So first
name let's check and make sure we're following all the instructions here.
Takes a campaign object returns a creator's first name. So we have done that here. So let's run. Looks pretty
that here. So let's run. Looks pretty
good. Nice. And we have a little quiz here. So refer to the following object.
here. So refer to the following object.
How can we access the name Jensen? So
without looking at the answers, let's see if we can figure it out ourselves.
So Jensen is this name here. So Jensen
is the name of the CEO in employees in the company. So we can just say I think company. Employees.
CEO.name. Company's employees. Oh, I'm
sorry. I forgot CEO. Company employees
CEO name. So, company employees CEO name,
name. So, company employees CEO name, not Jensen. That's doesn't seem right.
not Jensen. That's doesn't seem right.
Company employees CEO name. I think
that's right. The next one, just in case. Company employees CEO Jensen.
case. Company employees CEO Jensen.
Jensen is not a property, so that's not it. Company employees CEO. That's only
it. Company employees CEO. That's only
going to return the CEO object, not the name. So I think that we have the right
name. So I think that we have the right answer here. Company employee CEO name.
answer here. Company employee CEO name.
Yeah. Nice. Okay. So it says that uh nested data can quickly become hard to work with. That makes sense because if
work with. That makes sense because if you have a ton of nested objects, then you know it's going to be kind of confusing when there's tons of different properties and objects kind of flying around. When using the normal dot
around. When using the normal dot operator, if the object on the left side is null or undefined, you'll get a type error at runtime. But we have a new operator that we can deal with this the optional chaining operator. So it's a
question mark with a dot. All right. So
let's check out this code example here.
We have an object tournament and it has prize as a sort of child object. And
then at the bottom we are creating a property or creating a variable h that's supposed to have a value of tournament referee height. But height or referee
referee height. But height or referee doesn't exist in this object. we only
have prize, so it's going to be undefined. And so it's going to throw an
undefined. And so it's going to throw an error. So to prevent that error from
error. So to prevent that error from happening.
If you're not sure whether the referee property exists, what you can do is instead of just saying dot referee.
We can say referee question mark like does this exist and then if it does return the height property. Okay, so
that's kind of nice. All right, let's check out the assignment. So the textio database is only going to save a value if the value is truthy. If it's falsy, it'll ignore it without errors. So look
at the test cases to see the shape of the campaign object and the nested properties. So let's take a look at
properties. So let's take a look at that. Okay. So in the cases, we have a
that. Okay. So in the cases, we have a campaign here.
There we go. Yeah, campaign is there. It
has a name, message count, creator, location. So what do we want? And I
location. So what do we want? And I
guess we can check these boxes. We want
to get the campaign and return the region string if the campaign has one.
So here otherwise it'll return undefined. So we're not sure if the
undefined. So we're not sure if the region string exists.
Okay. So we should be able to do this with one line. So let's try return campaign dot and then what was it?
Campaign and then where is region?
Region's in location. So campaign
location region campaign location region. So I guess the the dot thing is
region. So I guess the the dot thing is supposed to be here. So location exists.
But what if region doesn't exist? But
location does exist. I'm not sure.
Well, let's just try running this and see what happens.
Okay, it did work. So I think we are basically asking or sort of questioning if location exists and then if it does then we'll return region. So these are the different cases. So they all have a
location. Region.
location. Region.
Oh, this one does not have a location.
Yeah. And then this one has location. So
I think that's good.
All right. Nice. All right. So we got another little quiz here. So when to chain? So we should only use that
chain? So we should only use that optional chain operator when you expect that an object may not exist. For
example, user must have an address object, but the address object may not have a street property. Oh, this is actually what I was wondering last time.
So we wouldn't if it may not have a street property, we wouldn't use the optional chaining operator here because this is questioning whether address exists. So not it doesn't have anything
exists. So not it doesn't have anything to do with the actual street property.
But if not all users have an address, then we would use that chaining optional chaining property here cuz address may or may not exist. And then if the user
may or may not exist, then we could use it there. Okay, so that makes sense. And
it there. Okay, so that makes sense. And
then we just don't want to overuse it.
That makes sense. Okay, cool. So the
quiz question, you should use optional chaining when it's expected an object may not exist. There we go. Okay, next question.
exist. There we go. Okay, next question.
Error messages make programming and debugging. I'm going to say better
debugging. I'm going to say better because if you don't have an error and it just fails silently, then you know, you may not find out there's a problem until much later. So, I'm going to say
error messages make programming easier.
Yeah. All right. Lesson nine. Object
methods.
So, I think methods are kind of like functions. Methods are functions that
functions. Methods are functions that are defined on an object. Okay. So, they
are kind of like functions.
and they can access and change the properties of the object. Oh, that's
interesting. And then it's using this.
So let's look at the example here. So we
got a object an object called person and person has first name property, last name property and then has a function here get full name which returns the
first name value and the last name value separated by a space. So that's
interesting. I wonder if that's kind of part of the whole JavaScript like functions as values thing where you can treat functions the same way as like any other value. Um I don't know if that's
other value. Um I don't know if that's part of this or not, but that's cool that you can do that with functions inside objects. So let's check out the
inside objects. So let's check out the assignment. Complete the get remaining
assignment. Complete the get remaining messages method inside the campaign object.
The method should calculate and return the number of remaining messages user can send. So that will be
can send. So that will be max messages minus sent messages.
Okay. So get remaining messages will return max messages or actually sorry campaign
dot max messages because it's a property of the campaign object minus campaign.
sent messages. I don't know if I need a semicolon there. Yeah, I guess I do. So,
semicolon there. Yeah, I guess I do. So,
let's double check the instructions again.
Completely get remaining messages. Okay,
so I think that's right. Oh, I guess I need to use this. This is just kind of the current object.
There we go. And we want to use this because it's like inside the campaign object is my guess. Okay, let's try it.
Looks like it passed, which is good. So,
I think we're good to submit. All right.
Nice. Okay. Methods mutate. Methods can
change the properties of their objects.
Okay, that makes sense. So, here we got a tree object with height color and then a function cut, which divides the height
by two, I think. Yeah.
So, when we run tree.cut, it's going to have the height be 128 instead of 256.
And then if we do it again, it'll be 64.
So it's actually able to change the value of this height property. That's
pretty cool. You might be wondering, I thought tree was a constant. I was kind of wondering that. And you're right, but the const keyword doesn't stop you from changing the properties of an object.
Okay, so I guess that means we can change the properties that are, you know, already inside the object. We just
can't like change the value, the overall value of tree. It only stops you from reassigning the variable tree in this case to a new object. Okay, that makes
that does make sense. So we what we cannot do is say after this say you know tree equals and then like some other object but we can change the properties
inside the object. Okay. So it's good to remember. So in the assignment we want
remember. So in the assignment we want to complete the send message method which is here. For now it should simply increment the campaign's send messages
counter by one. So that's going to be this property here. Okay.
So just going to use example code as reference. So in the function we're
reference. So in the function we're going to say this dot sent messages and then increment it by one. So I think
this should be good. Yep, it passed. So
let's submit. Nice. All right. So
initializing props. So if a property a key doesn't exist when we try to access it, it's just going to return undefined.
And we can check for this by using the not the exclamation point operator because undefined is going to be false.
So let's check out this example here. So
we have the balances object here. It has
three keys lane, Brianna, John. And then
we want to check if the balances.bob
property is false. If it is false, meaning it's not true, then we're going to set we we'll actually create a new key for Bob and set it to zero. So,
here's a quiz here. By the end of the code, how many keys will the balances object have? Well, it started with three
object have? Well, it started with three and Bob doesn't exist, so we're going to add Bob, so I'm assuming four.
Yay. Lesson 12 is about strings as keys.
That's interesting.
So if we know the name of the property, we can retrieve it with, you know, desk.height.
desk.height.
But what if it's a string? So for
example, what if the user enters a string and you need to use that as a lookup key? So, I'm guessing if there's
lookup key? So, I'm guessing if there's maybe some kind of form and the user kind of chooses what property they want to retrieve, then we could be working
with strings and we'll have to figure out how to get the property that matches the string name. So, in this example, we
have a desk object and it has a wood property and a width property. So, the
way that we've been using before to get the the property for the wood is desk.wood. would we can also if it's a
desk.wood. would we can also if it's a string say desk and instead of a dot we have square brackets and then the name of the
property as a string then we can also do it make it into a variable and then use a square brackets again with the variable name. Okay, that sounds like it
variable name. Okay, that sounds like it is very useful. So here's an example. If
we want to get last name from the users object then based on the first name then we can get users and then in brackets
first name. Okay. So in the assignment
first name. Okay. So in the assignment we need to complete the get provider count function here. It takes two parameters. The provider which is a
parameters. The provider which is a string. So it's like the name and then
string. So it's like the name and then an object counts.
So in this counts object, each key is a provider name and then the value is a number of phone numbers associated with that provider. Okay, so it's a bunch so
that provider. Okay, so it's a bunch so it's a bunch of list items. It's a so it's a list of a bunch of different providers along with the number of phone numbers each provider has based on their
name. Okay, so the function should
name. Okay, so the function should return the count of phone numbers for the given provider. If the provider doesn't exist in the counts object,
return zero. So let me just start by
return zero. So let me just start by doing assuming that it's going to exist first. So I'm going to say return counts
first. So I'm going to say return counts is the object and then square brackets and I guess provider. Although I think maybe this needs to be a string. Okay,
just out of curiosity, I'm just going to run this and I'm assuming it's going to fail, but I just want to see what happens. Okay, so it passed for the ones
happens. Okay, so it passed for the ones that weren't zero.
But maybe it's better to do something like this. Just out of curiosity, I'm
like this. Just out of curiosity, I'm just going to try the dot.
Okay. And that failed everything. So
yeah, because provider is going to be a string, we can't use the dot. So that
makes sense. And then we need to account for if it doesn't exist, it needs to return zero. So if not
return zero. So if not counts provider. So if counts provider
counts provider. So if counts provider counts provider with a square brackets is not true then return
zero otherwise return counts provider. So I think that should work.
Okay. And I feel like we could use that turnary thing for this. So return it's going to try to remove the other code we
don't need. So return not counts
don't need. So return not counts provider. So if counts provider is
provider. So if counts provider is return zero otherwise counts provider.
I think that will work.
So that does work. Okay we'll just try to submit. I think it will work.
to submit. I think it will work.
Okay. I was going to check the solution on this one. Oh, that's much more concise. Return counts provider
concise. Return counts provider or zero. Oh, that was cool. So, I guess
or zero. Oh, that was cool. So, I guess this means if counts provider is undefined, it'll return zero. Otherwise, it'll
return counts provider. Wow, that's very concise. Nice. I'll have to remember
concise. Nice. I'll have to remember that. If you're familiar with the self
that. If you're familiar with the self parameter in Python, well, the this keyword in JavaScript works in a similar way just with about 10,000 more edge cases. Take a look at this example where
cases. Take a look at this example where we have a very straightforward JavaScript object that makes use of the this keyword inside of a method. And it
works exactly as you'd expect. The get
full name method on the person object has access to the this keyword. And this
just refers to the object itself. So it
can access its own first name and last name fields by using this firstname and this last name. Again, very similar to how classes work in other languages. But
it starts to get really hairy because this isn't just limited to objects and classes. In the global context in the
classes. In the global context in the browser, the this keyword actually refers to the window. You can actually open up a browser, go to the dev tools, and type in console.log this, and you'll
get back the window object. And then in node, confusingly of course it's different. If you console.log this in
different. If you console.log this in the top level of a node script, you'll actually get back an empty object which refers to module.exports.
So again, not super useful and kind of confusing cuz it's different from everywhere else. Okay, so three
everywhere else. Okay, so three different cases to worry about, right?
We've surely got to be done now. Um, no,
because there's a little thing called ES modules that again changes the rules.
And when you're in the top level of an ES module, the this keyword in the global context, both in the browser and in node, is just undefined, which is probably a good thing because you
probably shouldn't be using it in the global context anyways. But again, just another edge case to consider. All
right, last one we're going to go over, arrow functions. So arrow functions are
arrow functions. So arrow functions are a new syntax for writing functions. An
old function looks like this, and an arrow function looks like this. It's
probably not fair for me to say old and new because it's not necessarily that arrow functions are better than old functions. They they're just a little
functions. They they're just a little bit different. Let's take a look at this
bit different. Let's take a look at this author object that contains a standard or traditional function. The this
keyword refers to the object itself.
We've been over this, but take a look at this object that now uses an arrow function. In this example, the this
function. In this example, the this keyword is actually undefined. And
that's because arrow functions inherit the value of the this keyword from their parent scope. So because this was
parent scope. So because this was undefined in the parent scope, it's also undefined within the object. You might
be looking at this and thinking that's insane. Obviously, I want a regular
insane. Obviously, I want a regular function. I want this to refer to the
function. I want this to refer to the object. And when you're working within
object. And when you're working within objects and classes, you're probably right. That is probably what you want.
right. That is probably what you want.
But there are some places where arrow functions are actually a lot more intuitive to work with. They became
really popular in front-end frameworks like React and View, particularly older versions of React and Vue that didn't use like hooks and composables because
in those frameworks, this was often used to contain the entire component state.
And when you drop down into a nested function, you kind of expected that this still referred to that component state and not a new context. So preserving the
context in that kind of nested function call just was what developers expected.
So arrow functions, you'll see them used a lot in those code bases and it does make a lot of sense and kind of makes things a little more intuitive.
Honestly, the takeaway from all of this is that only use this when you're sure what this is. And if you're not sure, debug your code and figure it out
because it's not always obvious and you might be able to clean up your code and write it in a more clear way so that it's obvious what's being stored inside
your variables. Okay, so we are talking
your variables. Okay, so we are talking about what this is and I guess it can be sort of not intuitive sometimes and we worked with it a little bit in I think one of the previous lessons where this
was like the object that we were sort of working with. So let's see some
working with. So let's see some different cases where this is used. So
global context so it could be the window object in a browser or module.exports
exports in NodeJS and then strict mode which we will I guess be getting into later. This is going to be undefined and
later. This is going to be undefined and then inside a method this refers to the object the methods called on. So I think this is what we were looking at earlier.
So in here we have the object and then we are logging what this is and this is basically this whole object just with
the the message property and then this message is the object and then the message properties value which is hello world. Okay. And then
it's used in arrow functions which the video kind of mentioned a little bit about. So we'll be looking at that next.
about. So we'll be looking at that next.
So the quiz says using this in object method refers to I'm assuming the object the method is called on not the method name uh not the global scope not the
browser window object yeah all right arrow functions so these are a newer way of writing functions in JavaScript the older way was using the function keyword and it says unlike let and con syntax
arrow functions are sometimes better but not always better so let's take a look at these okay so this is the older way of writing creating a function using the function keyword. So it's an the name of
function keyword. So it's an the name of it is add and it has x and y as parameters. Then we are declaring a
parameters. Then we are declaring a function using a variable. So it's the same as before using the function keyword but we are creating a variable
called add and setting it to be that function. Then with the arrow syntax it
function. Then with the arrow syntax it is kind of similar. So we are creating it as an add variable and then instead
of the function keyword we only have parentheses with the two parameters and then the arrow and then the curly brackets. So it's actually quite similar
brackets. So it's actually quite similar to the old way. So basically you're removing the function keyword. You have
your parameters here and then the arrow I guess kind of signifies that this is a function. Okay. So what's the
function. Okay. So what's the difference? They're always declared as
difference? They're always declared as variables. usually cons they handle
variables. usually cons they handle object scoping in a more intuitive way and then they don't work as constructors. So we are going to talk
constructors. So we are going to talk about these two topics later on. All
right, so let's check out the assignment. So he's forcing a team to
assignment. So he's forcing a team to convert all the classic functions to arrow functions. We want to convert is
arrow functions. We want to convert is spam me message to the fat arrow function syntax but don't change its internal behavior. Okay, so let's just
internal behavior. Okay, so let's just go back up to the code example. So
here's the old function function is spam message. So we need to remove the
message. So we need to remove the function const. I guess we'll have that is spam
const. I guess we'll have that is spam message be the name of the variable equals and then we have our parameter here and then equals angle bracket to
make the arrow and then the curly brackets and then all the code inside is supposed to be the same. Okay, so I think that should work.
Okay, I think that's pretty good.
There we go. All righty. So one of the differences that they had mentioned previously between arrow functions and I guess regular old functions is how this
is different between those two types of functions. So with the older function
functions. So with the older function not using arrows we can use this first name this last name because this refers back to the object author and then first
name and last name are properties of that object. So we can write this code
that object. So we can write this code to return them. Um, and the difference is with the arrow functions, the this refers to the global object. So, not the
author, but the the parent. And because
these only exist within the author object, it's going to be undefined. Um,
but it can be useful working with some JavaScript frameworks. So, that's why I
JavaScript frameworks. So, that's why I guess they're really popular. Okay, so
our boss is forced to change the arrow functions, but it's caused some bugs, and we want to fix the bug here. So
let's just run and see what we got so far with the initial code. Okay, so it's undefined which is kind of what we were expecting and that's because the this in send message doesn't refer to campaign
cuz we're using an arrow function. So I
mean I guess the only way to fix this is to not use narrow function is my guess.
So that works.
So I guess that's one way to fix it.
Although the boss like wanted arrow functions. I'm just going to try
functions. I'm just going to try something I don't think will work, but I'm just kind of curious. So, because
this is the sort of global parent, I wonder if we could say this.
Feel like it's not going to work. Yeah.
So, the best way to do this is not to use arrow functions.
Okay.
Nice. Okay. So, we're going to learn about spread syntax. So this is helpful to move.
We can merge and copy different object properties. That's pretty cool. So here
properties. That's pretty cool. So here
we have an engineering department object with a bunch of properties. And then we have a video department object. And then
at the bottom we're creating a new const with called all employees. And in that object we are merging engineering department and video department.
And the result is all the properties combined in one sort of object. That's
pretty cool. So this says that if properties have the same name the last or write most objects property is going to overwrite the previous ones. So that
definitely sounds like something that you need to be very careful about if you don't want to overwrite it. I think so.
In this example, there's a lane software engineer in engineering department and then there's a lane in the video department. Cringe YouTuber. And when
department. Cringe YouTuber. And when
you we merge them, the video department is going to overwrite any properties of the same name in the engineering department. So that's why lane is cringe
department. So that's why lane is cringe YouTuber instead of software engineer.
So we need to complete the merge templates function. It takes an object
templates function. It takes an object default templates and custom templates and then returns a merged object with a custom templates overwriting the default templates. Okay, so we want to do custom
templates. Okay, so we want to do custom after default templates because they will overwrite default. So const all templates
equals it's going to be an object dot dot dot default templates, dot dot custom templates.
Okay. And then we want to return all templates. So I think that looks right.
templates. So I think that looks right.
Just look at the previous code real quick. Yeah, I think I got the syntax
quick. Yeah, I think I got the syntax correct. Okay, let's run this. And looks
correct. Okay, let's run this. And looks
like it passed the tests which is good.
All right. So in JavaScript you can only return a single value from a function which we have learned.
But you can sort of get around that by if you want to return multiple values you can just return an object that contains those values. So that seems pretty useful. So in this example, we
pretty useful. So in this example, we have this function do all the math which has four different constants where it's doing different things. And then we're
returning an object here with the name of each of the constants. Then after we do that, then we can you know call the results object
and then with each of the different properties and that's this object here. That sounds good. So
object here. That sounds good. So
basically what we're doing is in the function we are creating a constant that runs a function with you know specific
parameters and then we can call the property of the object any of the properties of that object. Okay. So fix
a bug with calculate campaign metrics that it returns the defined metrics correctly. So what do we have here? So
correctly. So what do we have here? So
we have calculate campaign metrics. It
has sent open clicked as the parameters and then we have three constants. the
open rate, click rate, and conversion rate. Doing some math with these
rate. Doing some math with these numbers, and then at the bottom, it's returning open rate, click rate, and conversion rate. So, the names seem like
conversion rate. So, the names seem like they're matching, but obviously there's a bug in this. Let's just run this and see what the bug is. Okay, everything is undefined. So, if we look at the
undefined. So, if we look at the example, oh yeah, so we can look at the return line here. So, there's no curly brackets creating an object. So, we need
to do that here. Let's return and then outside of the semicolon closing curly brackets. And that should work. Let's
brackets. And that should work. Let's
try running again. And it looks like it passed.
And there we go. Okay. Dstructuring.
So it sounds like if you don't want to keep having to use the dot operator when you're sort of getting properties out of an object, you can do something called
dstructuring to unpack the object properties more easily. So when we do have to use a dot property looks like in this example we have created an apple
object with two properties radius and color and then we want to get those values out of the apple object and we want to basically create variables for
each of those properties so they're the same name and then set them to the value of those properties. So if we don't want to do that, the more I guess short way of doing that is set one const and then
the const is an object containing radius and color which are which match the names of the properties from the apple object which we declared earlier. It's
almost like when we're creating the object, we're like packing these properties into a box and then with this dstructuring we're basically like unpacking the box and taking the
properties out of it. So that does seem a lot more concise and nice. And here's
another example of using this. So in
this function get apple, it contains an object apple and returns it. So it
returns this object apple that has radius and color properties. Then to
dstructure it to unpack it, we are creating a const of this object with properties that match the properties in the apple object. and then we're setting
it to the the function which returns the object itself. So that's why when we log
object itself. So that's why when we log the radius and color they are returning the values of these properties. Okay. So
now we need to use dstructuring to assign open rate, click rate and conversion rate on line 14. So here's
line 14 and what we want to do is assign open rate, click rate and conversion rate. So this calculate campaign metrics
rate. So this calculate campaign metrics is going to return an object containing open rate, click rate, and conversion rate. So I think what we want to do is
rate. So I think what we want to do is kind of copy what we have here with the get apple thing. So we want to create a new const and it's going to be an object
and we want to contain all the properties from the object inside the calculate campaign metrics function. So
actually we can just copy this because they're separated by commas. I guess we don't need to come after the last one.
Let's just try to maybe have it all in one line. Probably doesn't matter, but
one line. Probably doesn't matter, but okay. So, here's the object
okay. So, here's the object and then we want it to be the function.
So, calculate campaign metrics with these parameters. So, let's just try to
these parameters. So, let's just try to run it.
Okay. Okay, so looks like it's returning stuff and you know open rate is opened divided by cent.
So 800 divided by a,000 that yeah 08. So
I think the math is right. Okay, cool.
All right, nice. All righty. So we are talking about how methods in JavaScript are not bound to their object. So the
method is the function inside the object. So if you try to use the method
object. So if you try to use the method as a callback function, which I believe is the function that you run when everything else is done, you may run
into issues with this keyword. So in
this user object, we have a name and then we have the say hi method. And we
can run user.hi function. And that's
fine outside of the object. But if we try to say just say hi, it's not going to it doesn't exist outside the object.
So it's going to be undefined. Okay. So
in this example, we have a user object with first name, last name, and then get full name is the method inside there.
And then we have a get greeting function which has two parameters. An
introduction text and then a name callback which is the callback function.
So if we say user.get get full name.
That works because we're saying user dot. Um, but if we try to run the get
dot. Um, but if we try to run the get greeting function with hello's introduction and then user.get fullname
trying to get the full name here.
That is not going to work. It's going to be undefined. So to make it work, we
be undefined. So to make it work, we need to bind it to the object with the bind method. So we can create a new
bind method. So we can create a new constant called bound get full name and then user.get full name. So this works.
then user.get full name. So this works.
user.get fullname but then dotbind and then you bind it to the object that it comes from. Okay. And then you can use
comes from. Okay. And then you can use this as a callback function. Let's see
what what we have to do here. Fix the
bug on line 19 so that this correctly references the scope of the campaign object. So let's take a look at the
object. So let's take a look at the campaign object. So it has name, max
campaign object. So it has name, max messages, sent messages and then send message is the method here which increments the number of sent messages.
Then we have this welcome function send welcome with the name and then the callback function and then logs this message here with a name and then it also logs the campaign sent messages. So
I think this is what is not going to work or no that should work but yeah this is what's not going to work.
campaigns send message a send message is a method so this is what we need to bind to the object. So we'll just kind of do
the same thing conb bound send message and we set that to campaign dot send
message I think. Yeah. dot send a message dotbind to the object which is campaign and then
instead of campaigns send message we can say bound send message. So we're binding send message to campaign. Okay. I think
that is correct.
Yeah.
Looks like it works.
Cool.
Yay.
All right. So, I think that was the last lesson in chapter 4 dealing with objects. So, all right. We're making
objects. So, all right. We're making
pretty good progress here.
All right. So, we are now on to chapter five. So, in this chapter, we're going
five. So, in this chapter, we're going to be talking about classes. So, it says here that classes in JavaScript are a template for creating objects. Okay. So
let's we'll find out what this means. So
with JavaScript, you can create objects without using classes, which is what we've been doing in the previous lessons, but classes are still going to be useful. And let's kind of look at
be useful. And let's kind of look at this example and see why. Okay, so here we are creating a new class called user.
And then in the user we have this constructor method which takes two parameters name and age. And then in that we are setting the user's name and
age to whatever the value of the parameter is. Okay. So that's the class
parameter is. Okay. So that's the class and that's supposed to be the template.
So then below that we are creating a new const called user and this user is
going to use a new I guess instance of the user class and then setting the name to be lane and then age to be 100. Okay,
so this makes sense because let's say we wanted to create you know more users.
Before when we weren't using classes, we had to, you know, manually say, you know, add name colon, you know, whatever the value of the name you wanted it to be and then age colon whatever your age
is. And you'd have to kind of do that
is. And you'd have to kind of do that manually for each property. But because
we're kind of, you know, creating a template for what the user fields should be, name and age, we can basically just reuse the user anytime we want to create
a new user without having to manually type out the the different fields. So
that's definitely very handy and a lot more efficient. So, okay, that seems
more efficient. So, okay, that seems pretty cool. So, let's look at this
pretty cool. So, let's look at this assignment. Textial messages include
assignment. Textial messages include three properties: recipient, sender, and body. Okay, so we need to complete this
body. Okay, so we need to complete this class here by adding a constructor that initializes these three properties.
Okay, so let's kind of go back up here for a second. So inside our message class, we need to use the constructor method and then in the method is going
to be the properties. So the first one is recipient recipient and then sender and then body and then the constructor
inside the curly brackets there we're going to set the values of these in this message class. So this whatever the
message class. So this whatever the current message is setting the recipient to be the value of the I guess I could
just copy and paste these recipient in the parameter and then this sender is going to be the value of sender and then this
body is going to be the body. Okay, that
looks pretty good. Let's just try to run this and see what happens.
Okay, there we go. Nice. I've reached level 10. All righty. So, we're going to talk
10. All righty. So, we're going to talk about private properties. So, by
default, all properties of a class are public, meaning you can access and modify them from outside the class. So,
if we look at the code here, we have a movie class with a title and a rating.
And then we are creating a matrix movie constant with the movie class. And then
we're setting the title and the rating to be the matrix in 9.5. And then we are getting the title. And then we can change the title. We're setting the matrix movie.title to be a new value.
matrix movie.title to be a new value.
The matrix reloaded. And then if we get the title again, it's going to have changed. This is pretty similar to what
changed. This is pretty similar to what we had done with objects that don't use classes. We could change the properties
classes. We could change the properties um after we've created that object. But
what if we don't want the title to be able to change in our code? We can make the title private by prefixing it with a hash and declaring it at the top of the
class. Okay, let's see how that looks.
class. Okay, let's see how that looks.
So here is again the movie class, but this time we've declared the title with a hash at the beginning. And then when we are setting the value of it, we're using that hash. So this indicates that
it's private. So this means that when we
it's private. So this means that when we are creating our matrix movie with the matrix and then the rating, we can't actually get the title because the title is a private field. Private field title
must be declared in an enclosing class.
Okay, so we can't we can't get the title because it's private. We can't get it outside of the class itself, but we can access it inside the class. So here's
the movie class with the private title property. But then inside the movie
property. But then inside the movie class still there's a method get title all caps. And just to remind myself
all caps. And just to remind myself method is a function inside an object.
So get title all caps you know retrieves a title and then it makes it uppercase and this works because this is inside the movie class. Okay. So that makes
sense. And then at the bottom here we
sense. And then at the bottom here we are creating the matrix movie like we did before but this time we can run the
get title all caps method because that is not private and because this is running from inside the class this can access the title without you know throwing an error. Okay. So
encapsulation encapsulation in JavaScript is typically enforced at two levels. So the class level, so what we
levels. So the class level, so what we were looking at just now, public and private methods using the hash for private fields, and then the module level, exporting only what you want to be public, and we're going to get to
JavaScript modules later on. Okay, so
let's check out the assignment now. So
textio messages have a created at field that stores the date the message was created. And we want to change it from
created. And we want to change it from the default public to be now a private field. And that is created at that's
field. And that is created at that's this one here. So what we want to do is declare it as a private property. Let's
look at the code again. So before the constructor, we declare the created at property and then when we are setting the value of
it, we use the hash again to indicate that we're using the private property.
Looks good to me.
All right. Nice. Okay. So we are now going to look at static methods. So what
are static methods? We've worked with I guess regular methods and properties.
Static methods it says that static methods and properties are bound to the class itself not the instance of a class. So if you create an object based
class. So if you create an object based on that class template you cannot access static methods or properties. Okay. So
let's look at the example code here. So
we have a user class with name and age.
And then with that user class, we're creating two instances of it, Lane and Allen. And then for each of those, we
Allen. And then for each of those, we can retrieve the name property from the object. Okay. So yeah, so when we create
object. Okay. So yeah, so when we create a static method or property, the object instances cannot access it. So what are they used for then? So static members
are often used for utility functions for the class itself. So here we have our user class like we had above except now we have a static property called numbum
users which starts at zero. So this is I'm assuming going to track the number of users and then in the constructor. So
anytime we are creating a new user it's going to not only set the name and age properties but it's also going to increment the num users static property
by one. And then below that we have a
by one. And then below that we have a static method get num users and this is going to return whatever the current number of users is that's being you know
saved on the class. So with these static properties and method we are first creating one instance of the user and then if we run the user.get num users
static method it's going to return one cuz that's you know it's been incremented from 0 to one. And then if we create another new user, then if we run the get num users static method again, it's going to return two. And
then we can't run get num users on the instances of the user like Lane or Allen. We can only run it on the class
Allen. We can only run it on the class itself, which makes sense. Okay, so
here's our assignment. Use static
properties to implement a new static get average message length method. Okay, so
we're sort of tracking the average message length every time a new message is created. So in order to do that, we
is created. So in order to do that, we do need to track the total message length of all messages sort of combined together and then also the total number of messages. And then we're going to
of messages. And then we're going to round to two decimal places. So the
round function, whatever's inside the parenthesis is going to get rounded to the nearest whole number or integer. And
you can get two decimal places by first multiplying whatever you have by 100. So
moving a decimal place two places. Then
it gets rounded. So any extra decimal place numbers that you had get kind of removed and you divide by 100 to get back to the number that you had before
just with two decimal places now. So
that seems pretty good. So let's look at our code is here and what do we want to do? So I think we want to
do? So I think we want to first create our static properties for the total message length and total messages. So we'll start by saying
messages. So we'll start by saying static and I guess we can just say total
message length and we'll start with zero like before and then we'll just copy and paste that and then total message number
or I guess num.
Okay, so we have our static properties.
So now every time we create a new message in the constructor, we want to update those numbers. So let's look at the example code again just make sure we're doing it right. So kind of
following this here, every time we have a new message created, we'll say message, which is the class dot and then
total message length. And we want this to get incremented by the length of the message, which I'm
assuming is the body dot length.
Okay. And then we also need to increment the total message number.
And I guess that just goes up by one. So
we can do the plus+. Okay. So that's our static properties. So now we also need
static properties. So now we also need to do the static method and let's copy the name.
So static get average message length and this should return the average message length. So how do we get the
message length. So how do we get the average? Let's start there. So it's
average? Let's start there. So it's
going to be the me oops the message total message length divided by the number of messages. So total
message num but we also have to round it. So let's look at this here. So math
it. So let's look at this here. So math
round and then the round in the parenthesis is the average which is everything up till here. But in also we want to multiply it by 100. And then
after the parenthesis we are dividing it by 100. And I'm just going to maybe put
by 100. And I'm just going to maybe put this on a new line so it's a little bit more readable. There we go. So this
more readable. There we go. So this
should return the average message length rounded to two decimal places. Let's run
this and see what happens. Oh, nice.
Okay. So that looks pretty good. Okay.
I'm just going to submit this.
Woo. Nice. All right. So let's check out a new part of classes that we're going to look at here. Getters and setters.
All right. So what these do is they let us get and set the values of properties and classes which make sense based on their name. So the interesting thing
their name. So the interesting thing here is that they look like regular methods but they're accessed like properties. Okay. So they're kind of
properties. Okay. So they're kind of like a hybrid type thing I guess. So
let's look at the code example here. So
we have our user class with name and age except this unerscore name is the name property instead of without the underscore like we had before. And the
reason for that is because we have this name method here created using the get keyword. And what this does is it's
keyword. And what this does is it's going to return the underscore name and then it's making it all uppercase. So
the underscore is so the names are kind of unique from each other cuz we're using down here when we're running this
getter method lane.name. Okay. So I
guess it's more efficient or I guess it's just less things to write when you are running this method and it's kind of returning you the name property but some things
have been done to it. Okay. So that was the getter. So now what's the setter?
the getter. So now what's the setter?
the setter probably sets um the property.
It lets us control what happens when a property is changed. Okay, so here we have the user class and this time we have underscore age. So we have the
getter get age to return the age value and then here in the setter it's checking that age is not negative. Okay,
so set age.
So if the number if the age is not negative, if it's a valid age, then it's going to set the underscore age property
from up here to be whatever the value of the age is. However, if it's a negative number, then it's going to throw an error. Okay, this is when you're trying
error. Okay, this is when you're trying to change the age property. So in the first line here, we're creating the new user with a name and an age, and the age is valid. And then we're trying to
is valid. And then we're trying to change the age to be a negative number.
And then that's when the error gets thrown. And then when we load the age,
thrown. And then when we load the age, it is loading the age that we had up here, which didn't change because 5 is not aval. They're saying here that he
not aval. They're saying here that he hates this. Yeah. When you get or set a
hates this. Yeah. When you get or set a value in the property field with the dot, you expect that you would be dealing with a raw value, not, you know, running a custom function. Okay. So the
advice is to only use it when you really need it. All right. All right, let's
need it. All right. All right, let's check out this assignment here. So, the
contact class has some problems. Allows any phone number to be set, even invalid ones. And it also lacks the correct
ones. And it also lacks the correct formatting. Okay, so we need to make
formatting. Okay, so we need to make sure the phone numbers are valid and then format them. So, add a setter for phone number that checks if the number is 10 digits long exactly. Then, if it's valid, sets the internal phone number
property. If not, throw an error. Okay,
property. If not, throw an error. Okay,
so let's do that first.
So the setter set I guess phone number phone number and let's kind of go back to the code example. Yeah, the setter.
So it's kind of like this where we're sort of validating. So the parameter is value. This is whatever you're setting
value. This is whatever you're setting trying to set the phone number to be. If
value length so it has to be exactly 10 digits. So if it is not
digits. So if it is not 10 then throw new error
and then here is the error message invalid phone number. So we'll just copy this
number. So we'll just copy this invalid phone number and then if the length is 10 then you know this error won't get thrown and then it'll proceed
to the next line to set this dot oh yeah it should be underscore. We'll change that underscore
underscore. We'll change that underscore phone number because we want this to be used in the setter phone number equals the value.
Why don't we just run this and see how this looks? Okay, so it did pass. It
should throw an error on invalid phone number, which it is doing. So this looks correct. So we'll just check those
correct. So we'll just check those boxes. And then the next thing is the
boxes. And then the next thing is the getter. And I think they had the get
getter. And I think they had the get before the set. So get get a add a getter for phone number that returns a number in the formatted style. So get
phone number and this is going to return well, let's just write this first. this
underscore phone number but we need to format it.
So returns a number in the formatted style.
So we need to I think do a substring number dot I don't I don't know if this is a good way of doing this but we want to first get the first three digits. So
I'm just going to start by just trying to make sure the substring is working correctly. So starts with the index. So
correctly. So starts with the index. So
zero to start at the beginning, the first digit. And then we want to go to I
first digit. And then we want to go to I think three. So I'm going to
think three. So I'm going to test this by I guess I need to create a
new contact. Cons contact one equals new
new contact. Cons contact one equals new contact.
And then I think it was name first. And
then here's the phone number. And I'm
assuming it should be a string because it's not like a number number. 1 2 3 4 5 6 7 8 9 0 and then we want to log
a phone number. So let's see if this works.
Okay, so here's what we are logging. So
it is successfully returning the first three digits. So that's good. So I think
three digits. So that's good. So I think we're going to do the template literal thing again. dollar sign curly bracket
thing again. dollar sign curly bracket curly bracket and then we're going to start with the parenthesis. I think
that's right and then ending closing parenthesis with a space at the end. So
let's run this again. Okay, so we got the parenthesis and the space. Nice. So
then after that we want to get the same type of thing here. I'm just going to go in a new line phone number substring and you want to
start at three and then go until six, I think. So, let's run this and make sure.
think. So, let's run this and make sure.
Okay. Oh, it's because it's in the template literal. So, it's going to be
template literal. So, it's going to be literal.
There we go. That's better. Okay. So,
that seems like that's working. We want
to add a hyphen and then get the from six to the end. So, I think if we just do that. So, 1 2 3 4 5 6 7 8 9 0. Okay,
do that. So, 1 2 3 4 5 6 7 8 9 0. Okay,
that does seem to match what we have here. So, I think that should work.
here. So, I think that should work.
Yeah. And then they did pass. Okay,
nice. Check the box and submit. Yay. All
right, we are on lesson five, which deals with inheritance. Okay, and I'm not going to lie, my brain is starting to hurt a little bit just cuz I'm well outside of I think my sort of
comfortable what I knew of JavaScript, which was very basic. So, I'm learning a lot of new stuff here, which is cool, but you know, it is, you know, it's not super easy. So inheritance, a class can
super easy. So inheritance, a class can inherit methods and properties from a parent class. Oh, that's interesting.
parent class. Oh, that's interesting.
Using the extends keyword. So I guess you can have parent classes and then child classes which will get the properties from the parent. So here we have a Titan class with a name property.
And then below that we have a beast Titan class that extends the parent Titan class.
Okay. And then here in the beast titan child class I guess you could say we have a speak method that will log this
message. So now below that we are
message. So now below that we are creating a beast titan that's a child the child class and then we can run the speak method. It seems like a good way
speak method. It seems like a good way to like keep things organized having like parent and child classes. And the
other thing you can do with this is that if we want to overwrite a method from the parent we can do that too. Oh okay
let's check this out.
So here's the parent Titan class all here with the name property and then the speak method and then in the parent Titan class it's going to log Titan
noises. Then we have the child class
noises. Then we have the child class down here which extends a parent class and then also has a speak method which says name
says I'm the beast Titan. Okay, so now we're going to look at using both of these. So
these. So pure Titan is the parent using the parent class new Titan with a message or with a text A's mom or name Aaron's mom
and then running the speak method will give you Titan noises which is from the parent method. Then below that we're
parent method. Then below that we're creating a child the beast Titan with the name of Zeke and then running the method on this which is made from the
child class. And here we have the
child class. And here we have the message from the beast titan child class. Okay, pretty cool. So let's check
class. Okay, pretty cool. So let's check out the assignment that we got here. So
we needed to create two new classes, SMS sender and email sender that extend the base sender class. Okay.
And then they're they should override the send message method which is this here. Okay. So first things first, let's
here. Okay. So first things first, let's create our child classes. We'll start
with I guess SMS sender. So class SMS sender extends sender which is the parent class
and then here has a send message method message and this should instead of throwing this error that we have in the
parent we're going to log this message here. Oh, wait. This is SMS sender log the SMS message here.
And we're probably going to want to use template literal. So back tick paste in
template literal. So back tick paste in our text and then we want to dollar sign curly bracket
and then recipient lowercase recipient and then message dollar oops dollar sign curly bracket
and then message lowercase.
Okay, that seems right. Let's just kind of take a look at this. So, we have SMS sender extends sender send message
message with the new message. Okay. Oh,
I forgot this. So, this recipient because it's coming from the property.
Okay. And I I don't think I need it for the message cuz message is not an actual property. It's just the parameter. Let's
property. It's just the parameter. Let's
just run this and see how it looks.
Local binding for export email sender not found. Okay. I guess I need to write
not found. Okay. I guess I need to write the rest of it too. So, I think this is right. So let's just copy and paste this
right. So let's just copy and paste this um email sender and then this one will have a different message sending email. So
instead of sending SMS sending email.
Okay, that seems correct. All right, now let's try running it again.
Oh nice.
Okay, I think we got it.
Nice. All righty. Let's check out this lesson here. So this one deals with the
lesson here. So this one deals with the super keyword. All right. It allows us
super keyword. All right. It allows us to call methods on an object's parent.
So, we've kind of been working with parent classes and then child classes.
And it's often used to call a parents constructor method when the child object has its own. So, let's check this out.
So, here we got the Titan, which is the parent. Its constructor method, you
parent. Its constructor method, you know, creates a name property and then we have the two string method and it returns Titan name and then whatever the name is that you set for the Titan. Then
below that, we have the child. So we
have the beast Titan which extends Titan and it has its own constructor and it looks like it's creating a new field power but it's also loading the name
from the parent. So I think this is what loads the name from the parent and then it's setting the power property. Okay.
And then we have a two-string method in the child as well. And what this does is it returns the I think the super string.
This is the parent and I think we can load this because of this super name up here in the constructor. So that's what
lets us access the parent method and properties I'm assuming. And then so it loads the parent to string method and then adds on comma power and then this power which is the new property that the
child adds. So then when we're creating
child adds. So then when we're creating a new beast titan with a name and then the numbers for the power level I guess
and then if we log the child to string method it's going to return Titan name Zeke and that's the this is the part from the parent without the comma and
then adds a comma and then adds on the power. So that's pretty cool. The child
power. So that's pretty cool. The child
can add on to whatever the parent like has. So let's check out the assignment
has. So let's check out the assignment here. sender classes send message method
here. sender classes send message method now handles the full message sending process. So they decided the sender
process. So they decided the sender subasses okay subasses is I guess what I've I've been calling it child classes but I'm guessing it's subasses. They
decide that the sender subasses which is I'm assuming SMS sender and then email sender should only format the message.
All right. So they will have a format message method that calls the base senders format message method. Then it
appends SMS or email in square brackets.
Okay. So let's kind of give this a shot here. So here's the sender parent. We
here. So here's the sender parent. We
have the constructor that gives us the recipient property and then we have the format message method which says to recipient message. So now we'll start
recipient message. So now we'll start with the subclass SMS sender and we want to do the constructor and
in the constructor I think we need to get the parents data. So the recipient and it's not
data. So the recipient and it's not adding any new properties. So I think that's all we need. So load the parents recipient with the super
keyword. And then we also need to get
keyword. And then we also need to get the message. Let's just get the method
the message. Let's just get the method going first. So, format message meth
going first. So, format message meth message message and then here's our method and we want to return in template literal the parent format
message method. It's kind of a tongue
message method. It's kind of a tongue twister. So, we access a parent with the
twister. So, we access a parent with the super format message. And this does have the
format message. And this does have the message yeah parameter from here. So, I think that should work. And then I guess it
just appends square brackets SMS. So yeah, I guess my question is I don't know if I need to write anything else in the child constructor to get the message
value from the parent. I guess the messages is just the parameter. So it's
going to be the parameter in the child format message method. So I think maybe this should be okay. Okay, I'm just going to try to run this just for the SMS sender to check it. Okay, so we failed one. And that's the email one
failed one. And that's the email one which you haven't done yet. But it did pass the test I'm assuming for the SMS test. So I think we're on the right
test. So I think we're on the right track here. So I'm just going to copy
track here. So I'm just going to copy what we got.
And then instead of SMS, it's going to be email. Let me just double check to
be email. Let me just double check to make sure it's not all caps or not. Oh
yeah, email. So this should work for email. Yeah, looks good. Okay, let's try
email. Yeah, looks good. Okay, let's try running our tests again. Yay. Okay, so I think we got this working.
Awesome.
All right, we are on chapter six now.
Prototypes. So, let's learn about what prototypes are. Prototypical
prototypes are. Prototypical inheritance. JavaScript's approach to
inheritance. JavaScript's approach to classes and objects can feel really weird if you're coming from C++, Python, or Java. And that's because JavaScript
or Java. And that's because JavaScript uses protottypical inheritance, which is fairly unique to it. The way I like to think about it is that JavaScript's inheritance is actually object first
instead of class first, which makes a lot of sense because classes weren't even added until way later. Prototypical
inheritance was working before the class keyword was even introduced to JavaScript. So, it's all based on
JavaScript. So, it's all based on prototypes. Every object in JavaScript
prototypes. Every object in JavaScript has a prototype which is stored internally in the_c_protoc field. Let's take a look at an example
field. Let's take a look at an example here. I've got an object that I've named
here. I've got an object that I've named pure titan, you know, for thematic effect. It's got a name property,
effect. It's got a name property, Aaron's mom, and it's got a speak method that prints a message to the console.
Now, this is just a plain JavaScript object. If we want to create a new
object. If we want to create a new object that has pure Titan as its parent, we'll need to use a prototype.
Or rather, we'll need to assign its prototype. And we can do that by
prototype. And we can do that by declaring a new object. We'll call it beast Titan. And we'll use the built-in
beast Titan. And we'll use the built-in object.create method to assign its
object.create method to assign its prototype, which you can think of as its parent, to pure Titan. So now beast Titan._proto
Titan._proto is set to pure Titan. And now,
interestingly, if we log the Beast Titan's name property, we'll see the Pure Titan's name value, Aaron's mom, because our Beast Titan object never actually had a name property. We never
set one. So, we'll actually walk up the prototype chain to find the name property of the parent object, and log that instead. But let's go ahead and
that instead. But let's go ahead and overwrite that property and method on the child object, Beast Titan in this case, and see what happens. We can set the name to Zeke and we can create this
new speak function that actually uses that name. So now when we call beast
that name. So now when we call beast titan.speak, it's going to use the
titan.speak, it's going to use the method on the beast titan object rather than walking up the prototype chain and using the parent objects method. The
same goes for the name property. Now
it's not just that one object can have one parent or one object can have one prototype. It's prototypical inheritance
prototype. It's prototypical inheritance because there's an entire chain of prototypes. When you create a new plain
prototypes. When you create a new plain JavaScript object, by default, its prototype is set to the built-in object.prototype object. That's kind of
object.prototype object. That's kind of the root of the chain. And its prototype is just set to null. Okay, so we've kind of covered how the inheritance works, but how do classes fit into this? So, as
I mentioned, classes were actually added later in JavaScript, and you can kind of think about them as syntactic sugar for prototypical inheritance, and they're really just templates for creating new
objects. So using the same example,
objects. So using the same example, let's create some classes. Let's create
a pure Titan class and then a beast Titan class that extends the pure Titan class. This is the syntax for that
class. This is the syntax for that parent child relationship. Now it's much easier to create a new instance of a beast Titan. We can use the new keyword.
beast Titan. We can use the new keyword.
And now because I didn't override the name field, the Beast Titan's name is still set to Aaron's mom. So when I call Aaron's mom.speak, I see Aaron's mom
Aaron's mom.speak, I see Aaron's mom says I'm the Beast Titan. But of course, I can override that field, set it equal to Zeke, call speak again, and now I get Zeke says I'm the beast Titan. So, this
all probably works as you'd expect if you're used to OOP languages. But there
is just one more thing to understand.
The prototype chain is going to look just a little bit different when you use the class syntax. Instead of our Beast Titan object having its prototype set to another instance of a pure Titan, its
prototype is actually going to be set to the Beast Titan class itself. or more
specifically a beast titan.prototype
object that you can kind of think about as the class itself and its prototype will be set to its parent class in this case pure titan.prototype. So the class
templates themselves have a built-in object that works as the prototype for new instances that are created. Okay, so
we've been working with classes in the last chapter, but now we are learning that classes are actually syntactic sugar for prototypes and they're much newer
and syntactic sugar meaning it's kind of like an abstracted way of working with the original sort of code um in a way that makes it kind of easier for humans
to work with. So classes are basically doing what prototypes are doing just with different syntax. So let's look at this. So every object in JavaScript has
this. So every object in JavaScript has a prototype. Okay. So when you inherit
a prototype. Okay. So when you inherit you are marking the parent as the prototype of the current object. Okay,
that makes sense. So this is kind of I'm assuming if I'm correct what led to the you know child class or subclass extends
parent class. So it's kind of the same
parent class. So it's kind of the same the same functionality. So the builtin object create method creates a new object with it prototype set to the given object. Okay, so let's check out
given object. Okay, so let's check out the example code we got here. So up at the top we are creating the uh parent object pure Titan. This is what we had
done before where this was the sort of original class.
And I guess with since it's an object, we don't need that constructor method, but instead we're sort of setting this name property to be Aaron's mom. And
then we have the speak method there.
Okay. So then when you run pure titan speak it returns you know what we have set up here. Okay. So that's the parent.
So now we are creating the beast titan the child with the object create. So
we're creating an object and we are setting the prototype to be pure titan.
So this is basically saying you know the beast titan is going to inherit whatever the the pure titan has. So if we
create this beast titan object from the pure titan then if we then we can access the name property that's on the pure titan parent. Okay. So that that makes
titan parent. Okay. So that that makes sense. And then we can
sense. And then we can change the name. So instead of Aaron's mom, we can use the object we created
here and set the name to Zeke. And then
we can overwrite the speak method that we had from the parent. So now instead of saying Titan noises, we are saying, you know, name says I'm the beast Titan.
So then when we run the speak method on the the child, the beast titan, it's going to change to the new value. So
yeah, it seems like it's pretty much doing everything that we were doing with classes. This is just I guess the
classes. This is just I guess the original version of doing of uh achieving this functionality. Since this
is the original and classes are newer, I'm not sure how often people are using prototypes. Maybe there's some slight
prototypes. Maybe there's some slight differences. I'm not really sure, but I
differences. I'm not really sure, but I think it's good to know, you know, where things came from. Okay, so the assignment, we need a new notification system that uses a new subclass of notification
to be able to send to a single users and to broadcast messages to all users. And
that's this is what is going to be new functionality for the subclass.
Okay. Use object create to create a new system notification object that inherits not from notification and then write a new method for system notification called broadcast that takes a single
message string as input and returns broadcast to all users. Okay,
so let's look at the first item. Use
object create to create a new system notification object that inherits from notification. We're going to look at the
notification. We're going to look at the example code that we had here. So here
this line here con beast titan equals object create pure titan. So that's what we're going to basically do there. So
system notification is the name of the new child I guess object you could say. So okay in our code this is the parent notification. So
we're going to say const and then the name system notification equals object create and then in the parenthesis is supposed to be the prototype. to the parent that
we want this to be based off of notification.
Okay, so we created the system notification object. Seems like everything we need to
object. Seems like everything we need to do for that and then write a new method for system notification called broadcast that takes a single message string as
input and returns that text. So we need to create the method called broadcast.
So if we look up here, we can do this kind of like that. So we'll say we have to use the child object system
notification dot notify and I think we need to have the recipient and message or hold on broadcast messages to all users. So all we need is the message. We
users. So all we need is the message. We
don't need to worry about the recipient.
I think the message has to be a parameter of that funk or of the method or maybe it just inherits it already. I
think we need to have that as the parameter.
I guess we'll see what happens. So, or no, this is wrong. Says notification.notify
wrong. Says notification.notify
equals function and then in here we want to return and then back tick. So, I think here is
where the message I think needs to go.
Not really confident about that, but we'll find out.
Okay, so the message string, we'll just copy this and then we need to replace this with the
template literal.
Okay. All right. Let's uh run this and see how it looks. Okay. Failed.
Broadcast is not a function. Okay. I
think I made a syntax error somewhere.
Oh, I'm sorry. It's broadcast, not notify.
That's the name of the function. Okay,
let's try running again. Oh, okay. It
looks like it worked. Cool. So, yeah,
the thing I wasn't sure about was the message parameter. For some reason, that
message parameter. For some reason, that keeps I feel like tripping me up, but creating this new broadcast function with message as a parameter means that
it's going to inherit the message parameter from the notification, the parent. So we don't have to like create
parent. So we don't have to like create it separately in the child object here.
Okay. All right. So I think we got that check.
Yay. All righty. So let's talk about prototype chains. So every object has a
prototype chains. So every object has a prototype and then that prototype can have its own prototype and so on. So if
you keep following all the way back as far as you can, it's going to eventually be the root object object will be kind of like the original prototype. and the
root object object does not have a prototype because it's the original. So
trying to get the prototype of that will result in null and then you can get the prototype of any given object using the object get
prototype of method. Okay, so let's check out the code here. So, we are looking at the pure Titan object and it
has a name Aaron's mom. And then from that Pure Titan object, we're creating a new object, Beast Titan. And it's going to be the Pure Titan is the Beast Titan's prototype. And then for the
Titan's prototype. And then for the Beast Titan, we've set the name to be Zeke. So then when we log the Beast
Zeke. So then when we log the Beast Titan object, we're getting back the object. You can see that with the curly
object. You can see that with the curly brackets with the name Zeke. And then if we get the prototype of the Beast Titan, we're going to basically return this thing
here. So name Aaron's mom. Getting the
here. So name Aaron's mom. Getting the
prototype of that is going to return the original object prototype.
And if you try to get the prototype of that, then it's going to hit the end of the chain. It'll return null. Okay. So
the chain. It'll return null. Okay. So
just a whole bunch of like inheritance going on here. How are parent members accessed?
So, you might think that using object create copies the properties kind of like how we created the beast titan, you know, with the pure titan as the
prototype, but it's not just copying and pasting the name Aaron's mom to the child. What it seems to be doing is you
child. What it seems to be doing is you when you create the beast titan based on pure titan and then you try to get the name property. It's not automatically
name property. It's not automatically going to belong to the beast titan. So it's going to look for that name property. Doesn't
find it. Then it's going to go back and check the prototype where it will find name Aaron's mom and that's where it gets the name property from. So let's
check out this assignment.
So in textio certain features are inherited based on the type of user. So
we got admins, moderators, and regular users. And we need to figure out if a
users. And we need to figure out if a user is an admin or not. Okay, seems
like a very common functionality you would need. So write a function is admin
would need. So write a function is admin that takes an object and returns whether that object's prototype references the admin user object. Okay, so let's look at the code here. So first we have a
user object named default user and then type is user. Then we are creating an admin user with user as the prototype
and for the admin user we're changing the type to admin. So we need to take and be able to check an object and check that object's prototype and see if that
is admin. So for example I guess if you
is admin. So for example I guess if you have an admin user I'm just going to write some sort of test code here. So
we'll say admin one it's going to be an admin object create and this is going to be based on the admin user object. So
the admin user will be the prototype.
And then let's try logging the object get prototype of admin one. Let me just make
sure I'm typing the right thing. Oh get
prototype of get prototype of Okay. So
I'm curious to see what will get logged here. We're getting the prototype of
here. We're getting the prototype of this admin one object that's based on the admin user.
So let's run this. Okay, we need to create that is admin function. So I'm
just going to create this here.
Function is admin. And then we'll just leave it blank for now. Okay. So up here is what we are returning from that code I wrote. So it's returning type is
I wrote. So it's returning type is admin. So I wonder if we
admin. So I wonder if we could kind of use that type field. So
now if we're trying to get the type of the prototype of admin one, it's going to return admin if they are an admin
user. So I feel like it could check if
user. So I feel like it could check if this is equal to admin, the string.
So I'm just going to try that.
And we'll have to change a few things here. So function is admin and then we
here. So function is admin and then we need to get the user prototype or the user um as a parameter I think. So we'll just say
I think. So we'll just say the function is admin takes an object and returns whether it's an admin or not. So we'll say
not. So we'll say obj object for the parameter and this is going to be whatever object gets passed
into the is admin function. So now we need to write a condition to check if this if the prototype of the object that
we've passed in if its type is equal to admin equals the string admin return true. I guess I'm sure there's a more concise way of
writing that. I'm just going to see if I
writing that. I'm just going to see if I can do this. So instead of the whole if thing, let's try return. Oops. And then
sort of delete all this stuff. So it's
returning whether you know. Oh, I think I have a syntax
you know. Oh, I think I have a syntax error. There we go. So it's returning if
error. There we go. So it's returning if the object of the parameter is type if the prototype of the object has a type of admin.
So I think that should work. And I'm
just going to delete this.
Okay, let's give this a shot.
Okay, looks like it is working. Cool.
Um, let's try submitting.
Nice.
Okay, so we are now on chapter 7 and we're going to be talking about loops.
So, in programming, from what I understand, loops is something that lets you run some code a repeated number of times. So, let's take a look at this
times. So, let's take a look at this traditional for loop in JavaScript to see how it works. So in the code example here, we are declaring our loop by using the keyword for. That's how you know
it's a for loop. And then what's going on is inside the curly brackets is this line of code. And this is what's going to be run a repeated number of times.
And then in the parenthesis, the contents of the parenthesis are going to tell us the parameters of a loop, like when it's going to start running and when it's going to stop running. So
let's take a closer look at that because that's kind of the sort of complex part of how loops work. So this first part, let I equal Z. What we're doing here is we're creating a variable I and it's
going to start off being equal to zero.
And usually we're doing this in order to sort of track where we are in the repeats.
And then the middle part, I is less than five. This tells us that we want to run
five. This tells us that we want to run the loop until I is no longer less than five. So this kind of tells us when this
five. So this kind of tells us when this is going to stop repeating. And then the third part, we are going to increment the value of i by one every time we repeat. So when we run this loop, it's
repeat. So when we run this loop, it's going to repeat this line of code and it's just going to repeat it until we sort of get out of the parameters of our loop like we said here. So the first
time around, I is going to be equal to zero because we initially set it at zero. So the first loop, it's going to
zero. So the first loop, it's going to return zero and then it's going to increment by one. So, it's going to go from 0 to 1 on the next time around and then it's going to keep going up by one
until I is equal to 4 and then it's going to stop because the next time around I would be equal to five and that would be outside the parameters of our I is less than five. So, it's going to
stop running at that point. So, this is the traditional loop and let's check out the assignment now. All right. So in
this assignment, we need to complete the bulk send cost function. And what it does is it's going to calculate the total cost of sending however many
number of messages we have here. And we
need to dictate the following rules. So
each message is going to have a base fee and that base fee is going to be the same no matter what. But then what becomes a little bit more complex is each message is going to also have a
dynamic fee. And this dynamic fee is
dynamic fee. And this dynamic fee is what changes. So the first message, the
what changes. So the first message, the dynamic fee will be zero. The second
message is going to go up by 1 cent and then it's going to keep increasing by 1 cent for each successive message. So
this is why we kind of need that for loop because if the only fee we had to worry about was that base fee, it would be very it would be very easy to calculate the total cost of you know the
fee. It would just be basically return
fee. It would just be basically return the number of messages times we'll just say base fee even though we didn't create the variable and that would be it. But because we have this dynamic fee
it. But because we have this dynamic fee that changes with each message that's why we need the for loop in order to be able to increment the dynamic fee
because that's what is increasing every time. So this is a really common
time. So this is a really common programming sort of design pattern and it's pretty helpful. So let's figure out what we need to do. So there are a couple things that we need to kind of
figure out here. So what I try to do is kind of make comments to myself if I need to remember things. So the first thing the the last thing we need to
calculate is the total fee of all messages. And this is what we want to return from this function. But
in order to do that, we also need to calculate, we'll just say calc cost of each message. So we need to use a for
each message. So we need to use a for loop to calculate the cost of each message because that's what's going to contain that dynamic fee. We need to basically keep a track of we need to
keep like a running total of whatever the total fee is going to be and just keep adding the cost of each individual message to that total.
So let's I think start out by calculating the cost of each individual message based on you know the order if it's the first second third fourth etc.
So what we want to do is create our for loop then parenthesis we'll write the sort of parameters of our loop. So let I
equal zero. So you know cuz counting and
equal zero. So you know cuz counting and programming starts with zero and then we need to end the loop. So we only want to repeat it basically the number of times
that we have number of messages. So I is less than num messages because we're starting the first message is going to be I equals zero. So we don't want it to
be equal or greater than the number of messages and then we want to increment I by 1. So then in this curly brackets is
by 1. So then in this curly brackets is where we're going to actually calculate the cost of each message.
So I'm just going to write some sort of maybe expanded code just so we can see everything and then we'll make it a little bit more efficient kind of at the
end. So we need to calculate the total
end. So we need to calculate the total cost of the message. We'll just say message cost equals we'll start off with zero. Then
we have the base fee equals 1. Actually,
I think we had talked about when we're using money and stuff, I think it they were saying it's better to use kind of the lowest common denominator. So,
because the dynamic fees are in pennies, I think everything should be in pennies.
And then we'll divide by 100 at the end.
So, we don't get any kind of weird rounding issues with the the programming. So, the base fee is $1. So,
programming. So, the base fee is $1. So,
that's 100 cents. And then we need to figure out the dynamic fee cost. We'll
just say dynamic fee and that's going to be so for the first message it's going to be zero. For the second message it's
be zero. For the second message it's going to be 1 cent. So that's when I equals zero. So I think we could say the
equals zero. So I think we could say the dynamic fee is going to be I and that's basically it because the first first loop I is equal to zero and there's zero fee which is correct. The
second loop um I is going to be equal to one and the second message will have a dynamic fee of one penny. So this should work. So then message actually sorry
work. So then message actually sorry this is wrong. Let message cost because we're changing it. So message cost
equals base fee plus dynamic fee. So let's actually just kind
dynamic fee. So let's actually just kind of run this code and just see if it seems like it's calculating the message
cost correctly. So I'm going to log
cost correctly. So I'm going to log message cost and let's actually use a template literal because I also want to return
the value of I. So I equals dollar sign curly brackets I message cost equals message cost.
So let's see how this works.
Okay, so down here when I equals zero, the first message, the message cost is 100 pennies. So it's $1 and that matches
100 pennies. So it's $1 and that matches what we have here. And then the second message I is equal to one. So the
message cost is a dollar plus one penny.
And then next one is a dollar plus two pennies and so on. So I think we're doing the math correctly here. Let's
kind of move this over a little bit.
Okay, so this seems good. So the next thing we want to do is we kind of need to keep a running total of the total cost of all messages because this is you
know what the bulk send cost function is supposed to calculate.
So I'm going to let we'll say total cost and we'll start off with zero.
And then what we're going to do is total cost equals total cost
plus message cost.
I think we can actually write that more um efficiently with increment total cost by current total
cost plus message cost.
Okay. So now let's end this by also logging the total cost dollar sign curly
brackets total cost. Okay. So now
at the end of the loop, we should get the total cost.
Okay, so we got 10 messages. Total cost
is 1045. That seems roughly correct cuz for 10 messages, each one has a base cost of a dollar and then it goes up by however many cents. So this seems roughly correct. And then we also need
roughly correct. And then we also need to make sure the math is right. Convert
the number of pennies to dollars by dividing it by 100. So total cost equals total cost divided by 100. And I think
we need to round it to in case there's weird decimal stuff. So math round total cost divided by 100 * 100 I think. And
then outside of the round it will divide by 100. So yeah. Okay. So now total cost
by 100. So yeah. Okay. So now total cost is $1045.
So I think the math is correct. So let's
return. I'm going to delete this.
So I think we can return this outside like outside of the loop.
So when the loop is done repeating, we'll return this number here.
Um, oops, I have an error somewhere.
Oops, left the equal sign in there. So
return math round, yada yada. Okay.
Okay, so it seems like it passed, which is pretty good. Let me get rid of some of the stuff I wrote here just cuz we don't need it anymore. Console log. I
think maybe we can simplify these variable things here. I just wrote it out to sort of show my work so I remember where I am.
So the total message cost for each message, it's going to be the base fee plus dynamic fee. So, we could just say base fee is 100 for now because the base fee is not
going to change. And I'll say let message cost equal 100 plus dynamic fee.
And the dynamic fee is really just I.
So, we'll just change this to I and then remove the dynamic fee. So, let message cost equal 100 plus I. And then total cost, we are incrementing it by the amount of the message cost. So, I think
that works. I actually wonder if we
that works. I actually wonder if we could make this even more short. We
could just replace message cost with 100 plus I. So I think that works even
plus I. So I think that works even better.
Okay.
So this is our sort of final function here where we are starting off with the total cost of zero and then we're writing this for loop where we are
adding $1 100 plus the number of cents based on the sort of the the placement in the repeats and then keeping track of the total cost and then we're returning the total cost converted from pennies to
dollars.
All right, so I think that works. Run it
one more time. Looks pretty good. And
submit. Nice. Okay. So, we also need to be able to break out of a loop even before we hit the end if need be. So, in
this example here, we're going from i= 0 to i is less than 10. But then if i is equal to 3, then we
10. But then if i is equal to 3, then we break out of the loop. So again, we're just logging the value of i. So it's
only going to go from i= 0, i= 1, i= 2.
And then when I equals three, it will break and it will not run this code here. So it's good to know no matter the
here. So it's good to know no matter the end condition when a break statement is encountered, the loop will exit immediately. Okay, let's check out this
immediately. Okay, let's check out this assignment. So we're completing this
assignment. So we're completing this message exists function which has parameters of messages which
is an array and then content. So what
are we doing here? So for each message we're going to print checking and then the content of the message. I'm assuming
where message is the message content in the messages array. Once it finds a message content that matches the given content argument which is here, it should also print
found message in addition to the initial checking message. Then it will break
checking message. Then it will break from the loop. Okay. So let's start by writing our initial for loop to loop through the messages in the array. So
we'll just have our little reference code up here.
So for let I equals zero. So I think what we're going to do is we're going to just loop through in order all the messages in the
messages array. So I is less than
messages array. So I is less than messages length. This will give us the number of
length. This will give us the number of messages and then I increment by one. Okay, I think that
is correct. So for each message we want
is correct. So for each message we want to log what was it? Print each message as checking. So
as checking. So checking and then dollar sign curly brackets messages
and we want to get the individual item in the array based on our current index.
So I um let's see if that seems right. Okay,
so let's just test what we have now and see what we get. Okay, so we are printing a bunch of messages which seems correct. And then we also now need to
correct. And then we also now need to add the second part. So we're looking for any message that matches the value of this content. And I'm assuming that's
this content. And I'm assuming that's going to be a string. So inside the loop when we're checking each individual message if messages
I equals content break. So I think that should do it
break. So I think that should do it cuz we're breaking after it prints the checking message. Yeah cuz once it finds
checking message. Yeah cuz once it finds the message content that matches a given content argument, it should also print.
So let's try that. Oh yeah, I forgot to do the found con. We'll just copy this found message. So it should be the same
found message. So it should be the same thing. Wonder if it would be more
thing. Wonder if it would be more efficient if we created a variable. So
const current message equals messages I and then we can replace
this with the variable. Okay, so now let's try rerunning it with our new found message and see if that does anything. Oh, cool.
anything. Oh, cool.
Okay, looks like it's working. So, let's
submit.
Yay. Okay, so in the previous lesson, we learned how to use the break keyword to completely break out of a loop and stop it from continuing. Um, in this lesson, we're going to learn about the continue
keyword, which is similar, but it is different. So instead of completely
different. So instead of completely breaking out of the loop, what continue does is it sort of stops just the current repeat, the current iteration, and then skips to the next value of i.
So in this example here, we're going from i is equal to zero up until i is less than 10, incrementing by 1. And
then inside the loop, if the current value of i, if it is divided by two and the remainder is zero, that means it's cleanly divisible by two, then we're
going to skip. We're going to continue the loop, but we're not going to write this code for that value of i. So what
this does is it's going to skip anytime i is equal to a even number. Sorry. It's
going to skip anytime i is divided by two, meaning if it's an even number. So
the result here is it's going to print one when it's two. Two is divisible by two. So it's going to skip that and not
two. So it's going to skip that and not print. Then it'll print three. And then
print. Then it'll print three. And then
four is divisible by two again. So it's
going to skip four and go to five, etc. So with that in mind, let's check out the assignment here. Okay, so we're breaking the fourth wall here and we are
working on this print primes function which will print all the prime numbers up to and including the max. So whatever
the max number is and we want to skip any numbers that are not prime. So
basically we're going to write a loop that will go from I'm assuming zero to whatever the max number is. If that
number is uh not prime, it's going to skip it and go to the next one.
So here's a pseudo code. So let's kind of look at this. So there's a loop for n from two to max. So we're starting at
two. Um if n is two, n is prime because
two. Um if n is two, n is prime because two is a prime number. Prime number
meaning it's divisible only by one and itself. So two is the two is a prime
itself. So two is the two is a prime number. So we want to print two.
number. So we want to print two.
Then we need to look for numbers that are not prime. So if n is even, meaning it's divisible by two, n is not prime.
So we're going to skip skip it and move to the next value of n. And then looks like we have another loop inside our first loop. So for
first loop. So for if i is starting at three up until the square root of n inclusive and then
going up in steps of two. If i can be multiplied into n meaning if n is divisible by i with zero remainder n is not prime and then we want to skip. So
then if this if the number continues, it hasn't sort of been skipped yet, then we know that that number is prime.
Okay, so we're doing some uh some math here.
All right, so we're skipping even numbers cuz num even numbers cannot be prime. Makes sense. And then we're only
prime. Makes sense. And then we're only checking up to the square root of n.
We're checking for if I * i is less than or equal to n. Let's start our loop here. So we'll start with the outer
here. So we'll start with the outer loop. So four let n equal to
loop. So four let n equal to until n is so we want to include the
max. So if n is less than or equal to
max. So if n is less than or equal to max and then we're going to increment by one. So if n is two then we want to
one. So if n is two then we want to print it and then if n is even meaning if n
getting the remainder of dividing it by two is equal to zero uh continue.
Okay. And then another loop inside here for a let i equal 3
until the square root of n. So how do you get the square root? I'm going to look this up.
mdn javascript square root. So,
square root. So, okay, math. Square root.
math. Square root.
So, yes, I I do not do programming very very much as you can probably see. So,
let I equ= 3 until the square roo<unk> of N. So, it's going to be like that for
of N. So, it's going to be like that for I is going from 3 until the roo<unk> of N inclusive in steps of two.
So, sorry, I forgot that part. So I is less than or equal to the<unk> of N. If
I can be multiplied into N meaning N / I get the remainder equal to zero then N is not prime. So continue and then I
guess my question here is if I'm doing continue in a nested for loop I feel like this will just skip inside the inner loop. So I'm not sure about this
inner loop. So I'm not sure about this treat of N. If I can be multiplied into N. N is not prime. Skip to the next N.
N. N is not prime. Skip to the next N.
Okay. So I'm not sure about like this part.
But if we get to the end going to log N.
Oh boy.
Okay. So I guess we'll just give this a shot.
Let's run this. Okay. Okay, primes up to 10 2 3 5 7 9. Uh-oh. 9 is not a prime number cuz it's divided divisible by
three. So where is 9 supposed to get
three. So where is 9 supposed to get caught? So this is if n is equal to two
caught? So this is if n is equal to two and 9 is not divisible by two. So I'm
assuming 9 should get caught here. So if
I is 9 or I'm sorry if the the yeah if I is 9 I is less than or equal to um
sorry so no n is 9. So if n is 9 the square root of n 9 is 3. If I is equal to 3, I is less than or equal to
the<unk> of 9. That will be true because 3 is equal to 3. So maybe the problem is here. If n is divisible by i. Oh, wait a
here. If n is divisible by i. Oh, wait a minute. In your code, you can set the
minute. In your code, you can set the stop condition as i * i is less than or equal to n. Oh,
I guess I think that's doing the same thing as what I did, but let's just copy what they said.
There we go. And I think I'm iterating correctly or I'm sorry incrementing. So
if n is 9, it's going to start at 3. 3 * 3 is equal to 9. So then it will move on to this if
to 9. So then it will move on to this if condition. If 9 is divisible by 3, then
condition. If 9 is divisible by 3, then it should continue. I'm going to log this
console log N= to N. I is equal to I. And then if this is true, I guess we
I. And then if this is true, I guess we don't need the back ticks. N is
divisible divisible by I. Okay. Okay. So this is I think the
by I. Okay. Okay. So this is I think the problem that I was thinking about because the continue is stopping this inside loop but it's not stopping the
outside loop because it continued here.
So I need to stop the outer loop if this is true. So I guess the continue has to
is true. So I guess the continue has to be outside the inner loop. Scoot this
down so I can see better. Here's the
outer loop. Maybe I need to do Yeah, I don't know how to stop the outer loop from the inner loop cuz if I add continue here, I don't think that's going to do anything. It's just going to stop every single time. Like it'll just
skip that step. For the inner loop, when a number has a factor, you should use the break keyword to exit the loop early. Oh, so if I use a break here,
early. Oh, so if I use a break here, it's going to completely break the inner loop. But then I think it's still going
loop. But then I think it's still going to continue to log. Okay, let's just see what the output is for this. Yeah, it's
still printing nine. For the inner loop, when the number is a factor, we should use the break keyword to exit the loop early. Okay. So if n is divisible by i,
early. Okay. So if n is divisible by i, we want to not print n. Yeah, I think this one is really has stumped me.
Let's just look at the solution.
Okay, so this first outer loop looks good. Um, oh, I should have continued
good. Um, oh, I should have continued here.
If n is equal to two or no, no, I Yeah, I didn't have the continue there. So
then if n is divisible by two continue that's right. Okay. Okay. This is what I
that's right. Okay. Okay. This is what I didn't do. I need to I needed to create
didn't do. I need to I needed to create a boolean and then check. So this is how you can get the value from inside the inner loop to
outside of it. Got it. Okay. So that's
good to know, man. Okay. So what did I not do? I did not
not do? I did not we don't want to continue because if n is equal to two we do want to print two actually yeah so we did but then we just
won't check the rest of the conditions so what I didn't do here was let is prime that's going to start as
true so it's a boolean and then if it is divis if n is divisible by i let's just remove my console log messages is
we will change the value of is prime to false. Yeah, false break out of the
to false. Yeah, false break out of the inner loop and then outside of the inner loop if
is prime. Oh, I see. So this whole this
is prime. Oh, I see. So this whole this thing will be inside here. Oh boy. Okay,
so I guess that makes sense. So, we need this variable because we can change it inside the inner loop, but then you can read the value of it in the outer loop.
Dang, that was pretty hard.
Um, let's try submitting now. And it
worked. All right, so let's check out the while keyword. So, we can do we can create while loops in JavaScript and it's going to keep repeating as long as
a certain condition is true. So in the example here we have a Jane object with the name Jane and then Jane has a mom whose name is Alice. Alice has a mom
whose name is Lily. Lily has a mom whose name is Granny and then Granny does not have a mom.
So what we're going to do in the code is we're going to start with the current person being Jane and then while the
current person is true or truthy we are going to log print the their person's name and we're also going to then change the current person to be the
current person's mom. So, we're going to start with Jane. Then, it's going to print Jane's mom, Alice. Alice's mom,
Lily. Lily's mom, Granny. Granny does
not have a mom. So, then it's going to break out of this while loop and then write this part of the code saying no more ancestors.
All right, so let's check out the assignment here. We charge exponentially
assignment here. We charge exponentially more money for each consecutive test text sent because we are a greedy sass.
So, let's see. So, we're trying to figure out the maximum messages to send.
We're calculating how many messages a user can send based on how much money they have, I guess, like in their in their budget or I guess the balance.
And the cost of the messages is going to be based on a multiplier. So, the first message only cost a penny, but each message after that is going to cost the same as the previous multiplied by some
kind of cost multiplier. So it's every success of messages is going to get more and more expensive.
Okay. So there's currently a bug in the code. The while loop responsible to
code. The while loop responsible to accumulating the total cost. It should
keep running until the balance runs out.
That makes sense. So let's check out our code.
So we have get max messages to send the function.
And then we have the parameter as a cost multiplier. Whatever that's going to be
multiplier. Whatever that's going to be could be dynamic. And then we have a maximum cost in pennies. This is kind of the the total budget, I guess you could say, available to work with. So we're
going to start by saying the actual cost in pennies is one. So one penny to start off, which is what they said in the description. And then we're going to
description. And then we're going to start saying the max messages to send is going to be one. So this is going to keep increasing. So the first message
keep increasing. So the first message will cost one penny. Second message will cost one penny times the cost multiplier. And then we're going to
multiplier. And then we're going to basically track the current balance which is going to be the maximum cost in pennies minus the actual cost. Okay. So
here's a while loop. So what's going on in here? So in the while loop we are
in here? So in the while loop we are think calculating the actual cost of the message times the
cost multiplier or sorry incremented by the cost multiplier and then we're going to subtract from the balance the actual cost.
So basically this is this first line is going to give you the actual cost of the current message. So, this number is
current message. So, this number is going to keep going up and then it's going to also track the balance and it's going to subtract whatever the cost of this message is from the current
balance. Then it's going to increment
balance. Then it's going to increment max messages to send by one. And then if balance is less than zero, max messages
to send I guess de increments decrements. Basically, we want to keep
decrements. Basically, we want to keep adding on, you know, more messages and more cost while I guess the balance is a
positive number. So, balance
positive number. So, balance is greater than zero cuz if it's zero, then we don't want to continue subtracting from it.
So, let's run this. Um, looks pretty good. All right.
good. All right.
Nice. All right. So now we're going to look at how to loop over the keys or the different properties of an object. So
we've been working with objects. Now
we're going to figure out how to loop through all the different properties or keys.
So this is useful when you're using an object like a dictionary or hashmap in other languages. Okay.
other languages. Okay.
So here we have an object Titan with a name, power, and age. So in this for loop we are looping over
key in Titan and then we're going to return the name of the key or the property and then the value of that property. So it's going to print out
property. So it's going to print out name that's the property itself and then the value of name for this object which is going to be Aaron and then the same for the other properties. Let's see. So
this is just kind of telling you the order. So it's going to start with non-
order. So it's going to start with non- negative integer keys. So numbers that are not negative and then it's going to go to the string keys and it's set in
chronological order of property creation. Okay. Okay. Cool. So let's
creation. Okay. Okay. Cool. So let's
check out the assignment here. So we
have we're storing server logs as structured objects but properties have changed over time. So each log entry actually has a different set of properties. That doesn't sound good.
properties. That doesn't sound good.
Let's complete the print matching properties function. So if a key in the
properties function. So if a key in the object starts with the given search term, it should print the key value pair in this format. Found key arrow value.
So key is going to be the property name.
Value is the value. So it's going to print found message ID sort of arrow to the value of it. Okay, cool. Okay. And
then we can use string prototype starts with to check if a string starts with a given substring. We'll remember that. So
given substring. We'll remember that. So
we want to loop over the properties of the message log message logs I should say. So let's check out the example code
say. So let's check out the example code again to be our reference for con key in I guess the individual
message log. So we'll loop through all
message log. So we'll loop through all the keys there. So if a key in the object starts with a given search term.
So if key I don't know if I'm doing this correctly at all starts with search term then we
want to print this.
So we'll log found key and then the value.
So we need to get the value of message log which should be we're going to follow this example here
the object which is message log and then we're getting the value of the key.
Okay, let's try running this. Yeah, key
prototype is undefined. So I definitely did that wrong. Let's see what MDN says.
starts with. Okay, so it's just dot starts with there we go.
Cool. Okay, I think that's right. Let's
try submitting this. Nice.
Okay, so I think that's all in uh chapter 7. So yeah.
chapter 7. So yeah.
All right, so we are actually I think almost halfway through the JavaScript course. We're on chapter 8 now. Yeah.
course. We're on chapter 8 now. Yeah.
And this chapter is going to be talking about arrays.
So with arrays, you can store multiple items in these array objects. And with
JavaScript, the items don't all have to be the same type. So if we look at the example here, in the first array, we have a bunch of numbers and then we have
a bunch of strings and then we have an array that has a boolean true. It has a number and then it has a string. So yes,
JavaScript is kind of loosey goosey as we know already. And basically the defining feature of an array is that the items are stored inside these square
brackets in the code. So that kind of tells you that it's an array and you can pull items out of the array. So for
example in this example down here we are getting the first item so index zero out of the array and that is the string banana.
And then you can add new items um to the end of an array. So we are creating this drinks array. It's empty
at the moment. And then we use the push method to add the lemonade item. And
then we can add um another item root beer again with push and it adds it after the lemonade. Cool. So let's check out the assignment here. Okay. So we
need to manage the message history of messages that have been successfully sent. So first we need to create an
sent. So first we need to create an empty array called sent messages. Then
we're going to push a string into the array. Then we're going to print the
array. Then we're going to print the array, push another string, and then print the array again. All right. So
we're going to create an empty array. So
const sent messages equals and then square brackets. And then we want to push the string welcome to
textio. So let's copy that. So then with
textio. So let's copy that. So then with the array sent messages push and we're going to add the string there.
Um and then use log array the log array function to print the array log array to print sent messages.
And then we're going to push another string.
So actually I'm just going to copy this cuz I think we're doing the same thing.
And then this time we are pushing this reminder string there. So it's going to add it to the
there. So it's going to add it to the end of the array. And then again we're going to print sent messages one more time. Okay. So I think that looks pretty
time. Okay. So I think that looks pretty good. So let's run this. So the first
good. So let's run this. So the first one we have just that first welcome to Texio item. And then we added the second
Texio item. And then we added the second item. And then when we print the array
item. And then when we print the array again, we have the two items. So yeah, that looks pretty good to me.
All right. So arrays have usually multiple items in them. So one important thing you need to be able to do is to know how many items are in your array.
And you can do that using the length property. So in the example code here,
property. So in the example code here, we have an array foods and it contains three items. So then when we get the foods.length property, it's going to
foods.length property, it's going to return three, which is the number of items. So let's check out this assignment here.
So we need to complete the get most recent user function. So if the usernames array,
function. So if the usernames array, which is the parameter of the function here, if it's empty, return null.
Otherwise, return the last username in the array.
Okay, so we need to return. So if
user names if it's empty it's going to be falsy I believe. So if we check if it's false meaning it's empty we want to
return null otherwise return the last username in the array. So how do we get the last username?
So if we go back to the example, this array had three items. And if we want to refer to them by the index number, burger, the first item will be zero.
Fries would be one, pizza would be two.
And the length is three for three items. So we can refer to the last item by getting the index number of the length minus one.
So to get the last item user names and we'll use the square brackets for the
index and we want to get the length minus one like that. So I think this
should work. Let's see.
should work. Let's see.
Okay, looks pretty good. Now I think we can make this code a little bit more compact. So I'm going to actually
compact. So I'm going to actually comment this out. Let's try to make this more like a oneliner with the uh turnary thing. So return and we want to check if
thing. So return and we want to check if usernames is false return null. Otherwise return
the usernames length minus one.
Okay, I think that should still work.
Yeah. Okay. So I'm going to delete this and let's try submitting.
What's going on here? Should return null for here. Okay, so we need to check if
for here. Okay, so we need to check if it's empty. So maybe if usernames
it's empty. So maybe if usernames length is equal to zero. That works for the test cases. So instead of it returning false, we're just checking if
the length is zero, meaning there's zero items. Okay.
And just out of curiosity, let's look at the solution here. Yeah, so length is equal to zero. So I was incorrect in thinking it would return false, which I guess makes sense since it exists, but
it just doesn't have any items inside the array itself.
All righty. Okay. So another thing you can do with arrays is using the spread syntax.
So we had used it previously for merging um different object properties. We can
do that with arrays. So in this example here we have one array nums with 1 2 3 and then we have a second array new nums and
in that we're using the spread syntax to merge items in the first array into the second array. So it's adding 1 2 3
second array. So it's adding 1 2 3 before 4 and six.
And then this is the final content of the new array. Nice. So it's kind of like where push you can just add items to the end of an array using the spread
syntax. It seems like you can add items
syntax. It seems like you can add items I guess from another array into um a second array and they can be added I'm assuming anywhere. Okay. So complete the
assuming anywhere. Okay. So complete the new up the upload new messages function.
It accepts the old messages array and then new messages array. And what we want to do is we want to combine them into a new array.
So let's create our new array. I'll just
say all messages equals spread syntax old messages, new messages and then return all
messages. Okay, so yeah, old followed by
messages. Okay, so yeah, old followed by new. So I think this should work. Let's
new. So I think this should work. Let's
see. All right, looks good. Um, okay.
I'm just going to submit this. Nice.
Okay, so we are now looking at the includes method. So with arrays, we can
includes method. So with arrays, we can use that to check if one of the items in the array matches you know something else. So we have this fruits array which
else. So we have this fruits array which contains apple, orange and banana and we are using the includes method to check if the array includes the value orange
for one of the items and it does. So it
returns true. But if we check for pair, pair does not exist in the array. So
this is going to return false. And we
can do the same thing with strings. So
we have a string hello world. We can
check if it includes world and it does.
So this will be true. But if we check if it includes banana, it does not contain the word banana. So it's going to return false. Okay. So we are going to be
false. Okay. So we are going to be working with the profanity detection. So
what we want to do is check if um the array of words, review words contains no bad words, one bad word, or
two or more different bad words. And
these are the the bad words, dang, shoot, and heck. Okay. So what we want to do is let's first check for the first word,
dang.
So if review words includes dang and then I'm just going to do this
for testing console log has den.
So let's run this.
So yeah has ding.
So that seems to be working. And we want to check for all of the other ones too.
And then we also need to figure out how to get the rating. So I think the rating is going to be maybe we'll use a number
for that. So let rating
for that. So let rating equal zero. So I think we want to count
equal zero. So I think we want to count how many if it includes Yeah. So if it includes dang rating
is going to increment by one and I think we can do this for all three words. So shoot
words. So shoot heck heck. So then if it includes dang rating
heck. So then if it includes dang rating is going to go up by one. If it includes shoot it'll go up by one. If it includes heck it'll go up by one. So it'll start
off as zero. So I think this should work. So we'll have the number. So then
work. So we'll have the number. So then
if rating is equal to zero then we want to return clean I believe. Yeah return. So if
I believe. Yeah return. So if
rating equals zero return clean else if rating
is 1 return dirty and then otherwise
return filthy.
Okay. I don't know if this is how efficient this is, but I think it'll work. So, let's see. Looks like it
work. So, let's see. Looks like it passes. I'm just going to delete my
passes. I'm just going to delete my console log here. I wonder if there's a better way of writing this that's more efficient. You know, I'm not really
efficient. You know, I'm not really sure. So, I think I'm just going to
sure. So, I think I'm just going to submit this.
Nice. And then let's check out the solution just out of curiosity. Okay. So
in the solution they created three different variables for whether it includes each of the three different words and then numbum
words equals zero. So they are did do something sort of similar as what I did but instead of I wrote out the whole thing in the conditional and they just
used the the boolean.
Um, and then the last part, yeah, seemed pretty similar. So, this is probably
pretty similar. So, this is probably better because maybe up front it sort of tells you what you're kind of measuring cuz I kind of included it in all of my different conditional statements, which
I think makes it takes a little bit more work to like look at it and like figure out what it's saying. Um, even though it does seem to work the same, but all right, cool. So, we're going to look at
right, cool. So, we're going to look at a new way that we can write for loops.
So before in our for loop, we would use the i variable to help us keep track of where we are in the loops. And every
time it repeats, it would increment.
With the new syntax, this does the same thing, but with a lot less to write. So
you can see here it says let wood of woods. And what's happening here is that
woods. And what's happening here is that the of woods, woods is the array that has, you know, the multiple items that we want to kind of loop through. And
then the wood singular is going to be the individual item. So
you you can make the wood variable, I think, anything you want. It doesn't
have to be wood, but it just kind of is more intuitive, I think, and it kind of shows what you're doing when you have the singular form of the word wood. And
then the plural form is, you know, the array or whatever group of items you are um looping through. So with that in mind, let's check out our assignment here. Okay, so we're still working on
here. Okay, so we're still working on the like profanity in the text messages and we're working on this get clean messages function and it takes in an
array of messages and each item in the array is a string which is the individual message and we want to filter out of this array any messages that
contain the the bad word. So whatever
that word is and then we want to add all the messages that do not contain the bad word into a new array. So let's start by
writing our for loop. So for
let and I'll say let's do message of messages just to make it a little bit shorter.
And then we're going to loop through each message. So for each message we
each message. So for each message we need to determine if that individual message contains the bad word. So if
message and we can say includes bad word then do nothing. So if it doesn't
include the bad word then we do want to add it to the array of clean messages.
So let's create our array call it clean messages. And there we go. So then if it
messages. And there we go. So then if it does not include the bad word we will add it with push message. Okay. And then
at the end we will return clean messages. Now the
instructions also say be sure to make the matching case insensitive. So if the bad word is all lowercase and the message itself has the word but it's uppercase or you know capitalized, we
still want that to match. And I think doing this will not match if the cases are different. So I think what we can do
are different. So I think what we can do is make both of them uppercase when we are checking if they match. So message
dot I think it's two uppercase. If the
message which has been made uppercase includes the bad word which has also been made uppercase just so they match then we'll add the message and this is you know not going to be made uppercase.
So it'll be the original message. So,
let's run this and see what happens.
Okay, looks like it's pretty good.
So, let's submit. Cool. And just out of curiosity, I just like checking the solution to see like how what I wrote kind of compares. Okay, so this one they
are making it lowercase, which I guess accomplishes the same thing as long as they're the same.
And then they made a new variable for the message. So
the message. So yeah, I think they kind of accomplish the same thing. I'm not sure which like approach is better, but I think what I wrote did work. So I think that's pretty
good. All right. Another thing that you
good. All right. Another thing that you can do with arrays is slice them. So you
kind of cut off different parts of it using the slice method. So let's take a look at this example here. So we have this animals array and it contains um
ant, bison, camel, duck, elephant and in the first line um we're doing animals slice two. So the number in here if
slice two. So the number in here if there's just one number that is the starting slice and it's going to slice at two. So ant is zero, bison is one,
at two. So ant is zero, bison is one, camel is two. So, it's going to slice at the beginning of two and then keep everything else to the end because there's only that one number in the um
in the slice method. So, that's why the result of this is camel, duck, elephant.
For the second line, animals slice 2, 4.
It's slicing again at two. So, 0 1 2.
So, starting with camel, 3 4. So, the
ending slice also is at the beginning of the item. So, it's going to cut off
the item. So, it's going to cut off elephant. So, we're just going to keep
elephant. So, we're just going to keep camel and duck. So, that's how I kind of try to remember. So, the number will tell you you're slicing at the beginning. So, the beginning slice will
beginning. So, the beginning slice will include that item, the two item. The
ending slice, which we had at four, will not include elephant because it happens before the elephant item. So again,
animal slice 1 comma 5 01. So we start with bison 2 3 4 and then five is after elephant.
So that's why this includes elephant and then we can also do negative numbers for slicing at least slice at -2.
So it's going to be 0 1 -2.
So the slice starts at duck and then there's only that one number. So it's
going to include the end of it. So then
animal slice 2 comma 1. So 0 1 2. So we
start at camel and then we end at -1. So
0 negative 1 here. So just camel and duck. And then if we just have slice
duck. And then if we just have slice with no parameters at all, then nothing will get sliced because you're not giving it an index. It's a little bit of
a you kind of have to count things, I guess. So I guess we're going to be
guess. So I guess we're going to be slicing in this assignment here. Okay.
So we are looking through the logs for a specific word. We want to complete the
specific word. We want to complete the split logs function searching logs which I'm assuming is going to be an array for a specific message containing the slug.
And the slug I'm assuming is a string.
So when it finds a message that contains the slug, we're going to return an object with three properties. All the
logs before the first log containing the slug. Okay. So we'll slice before the
slug. Okay. So we'll slice before the slug and then all the logs after the first log containing the slug. So then
we'll slice after. So basically
everything that does not contain the slug. So both before and after and then
slug. So both before and after and then the index of the first log containing the slug. Okay. And then if not found
the slug. Okay. And then if not found return negative one for the index and empty arrays for before and after. Okay.
So there's a lot going on here. So,
first thing I'm just going to see what is in the logs and the slug just so I can kind of try to picture it, I guess.
So, console log logs, slug. So, let's
kind of look at what we got. Okay, so
here is the logs array and there's just a bunch of little messages here. And the
slug that we're looking for is debug. So
um 1 2 3 4 5 the fifth message. So um
index 4 contains the slug debug debug info. So for before for this we want it
info. So for before for this we want it to contain all the logs before this log. So everything before debug
this log. So everything before debug info. So if we slice it this would be
info. So if we slice it this would be zero one two that's a long one three. So
we'd want to slice from I guess zero comma to three I think and then after all the logs after the first log containing this log. So if this was
three, this is four. So we want to start at four and then just four and then it'll go to the end. And we need to get the index of the first log containing
the slug. And this should be 0 1 2 3. So
the slug. And this should be 0 1 2 3. So
okay. So I think what we're going to have to do is loop through the logs. And
we do need to contain the index. So
let's write our loop first. And I'm
going to try to do it with that newer syntax. So for let log singular of logs
syntax. So for let log singular of logs plural. And then we want to track the
plural. And then we want to track the index.
So I'm going to start outside the for loop.
Let I equal zero because that's where we start counting. So in here we're looping
start counting. So in here we're looping through each individual log message. So
if the log message includes slug that will be the value of the that'll be this will be the item that we want to get the index
number from. That's kind of what all the
number from. That's kind of what all the different slices are kind of based around. So if the log message does
around. So if the log message does include that slug then what we want to keep eye at that value.
So I think we want to break out of the the for loop at that point. Otherwise,
if it doesn't include the slug, we do want to keep going.
So we will keep going and we will also increment I so that it, you know, keeps counting up. Let's just test this first
counting up. Let's just test this first to see if it works without an error. So
what I'm trying to get is the value of I. And for the first test, I think it
I. And for the first test, I think it should be three. So we're going to log I.
Okay, let's give this a shot. Okay, so
we do have three, which I believe is a correct index. So that's a good sign.
correct index. So that's a good sign.
So then we have the correct index.
So now we can start creating this return object. So I guess we'll start this
object. So I guess we'll start this after here. So I guess we'll say const.
after here. So I guess we'll say const.
I'm not sure what to call this. We'll
just say object equal an array or no, I'm sorry, this is an object.
Oh my gosh, I feel like I forgot everything that I learned in the previous lessons. I think this is right
previous lessons. I think this is right with the and then you have the properties followed by a colon. Um,
okay. So, it turn returns an object with three properties. Before, comma, oh my
three properties. Before, comma, oh my gosh. after
gosh. after comma and then I and this will be I.
So for the before value we want to slice our array of logs.
Slice we want to start slicing. So all
logs before the first log contain the slug. So I think we start at zero
slug. So I think we start at zero and then end at three to not to slice before the the three index item and then after is going to be the same
logs slice but this time we are starting after the log containing the slug. So if we start at three that would include that item.
So we want to do I + one I think and then just goes to the end. So this one will just have one
the end. So this one will just have one one number. Okay.
one number. Okay.
Not super confident about this, but we'll return object.
Let's see. Oh, one of them did pass. The
first one failed though. So let's
uncomment our console log of everything.
So this is the first one. That one was the one that I got right. So let's look at the it's failing test one process one. So I think it's this one that's
one. So I think it's this one that's failing.
Yeah, I I passed test zero for debug. So
this one that one at least worked. Let's
look at this second one here. The
slug is process one. So it is in this message, the second message. So 01 is at index one. So that's
index one. So that's I think the correct index. So it
expected the before to be yeah just that first item start but it got start and also process one. So why did it Oh, I'm sorry. No, it did have start. I'm not
sorry. No, it did have start. I'm not
sure why it's erroring out. Wait, why
did I write three here?
I think it's supposed to be I.
Oh my gosh.
Okay, that worked. Wow.
I feel like that happens a lot. You just
like make really silly mistakes. But okay, I think this works cuz it did pass the test. I'm just going to delete my
test. I'm just going to delete my console log. Okay,
console log. Okay, there we go.
No, why is it not working? Okay, so the additional test failed. Oh, I forgot the not found.
Okay, I totally forgot about that. Okay,
so if the slug is not found, what's going to happen? So if it if the slug does not exist in the logs,
then it's never going to do this. So
it's just going to keep incrementing. So we need to figure
keep incrementing. So we need to figure out a way to determine when it like hit the end of the logs and still didn't
find the slug.
So I wonder if that would be if let's say there's three items. I starts at zero.
So zero for the first index doesn't find it. It goes up to one for the second
it. It goes up to one for the second item doesn't find it. Goes up to two for the third item and doesn't find
it. And I think it'll increment one more
it. And I think it'll increment one more time. So
time. So I think it would be the length of the array. Okay. So in that case after we
array. Okay. So in that case after we end the loop if I
I have no idea if this is going to work.
Equals logs length.
Then we actually want to change I to be negative one.
And then we're going to assume that this condition will be met if it doesn't like nothing happens. So actually I think we
nothing happens. So actually I think we want the object to be we're actually going to initialize the object beforehand. So const object equals and
beforehand. So const object equals and this will have the default values if the slug isn't found at all.
So before would be an empty array after would also be an empty array
and then I would be -1.
So that will change if I is not the length of logs and then we will
change I think we need to change the properties actually. So instead of doing
properties actually. So instead of doing this we'll change the properties individually. My confidence level is not
individually. My confidence level is not high at all with this. I feel like I probably have a bunch of errors. Okay.
Well, the run tests seem to work.
Oh my gosh.
Okay. I definitely want to look at the solution on this one cuz that one was kind of hard.
I'm glad I got it though. Okay, so here they're setting it initially be negative one.
First instance I I was just using I which maybe was not the best choice. I
don't really know. Um, and then they actually did a traditional for loop incrementing I. Okay, it sort of
incrementing I. Okay, it sort of accomplished the same thing.
And then yeah, if first instance I equals1, that means it was never changed.
Then it's going to return this object.
Otherwise, it'll return. Yeah, pretty
much the same, just slightly different in how we set up the loop. So, I mean, I don't know which one's better. Maybe if
maybe they both are fine. But, all
right. So, that was slicing arrays.
Okay. So, I'm actually relieved this is a quiz cuz that last lesson was it used up a lot of brain power, I think. But
let's look at this. So like objects, the contents of const arrays can be modified. That makes sense. We can like
modified. That makes sense. We can like we could modify the properties of objects. We just can't like set the
objects. We just can't like set the object itself to something new. Um re we can't reassign it. So we can add and remove elements, but we can't set new array value using the equal sign. That
makes sense.
So for so in this example if we have a drinks array even though it's empty we can add an item with push but we can't reassign it to be you know a different
array. Yeah.
array. Yeah.
So I guess it is a little bit weird. So
can the elements of a const array ever be changed? Yes the elements can change.
be changed? Yes the elements can change.
And then the assignment operator equal sign can be used to reset the value of a const array. That is not true. We cannot
const array. That is not true. We cannot
use that.
Yay. Okay. So, looks like we can dstructure an array like we can with objects. Meaning you can kind of unpack
objects. Meaning you can kind of unpack them and set each item to be a variable.
So here in the example, we have a nums array containing um the items 1 2 and three numbers. Then we have a function
three numbers. Then we have a function that will double it'll take an array that has three items. It will double each individual item and then return them in a new array. So what we're doing
down here is we are creating a I guess dstructured array and we're setting it to be the value of the double function running the nums array.
So this should return an array containing 2 4 and six. But because we did it this way, dstructuring it, we can individually pull out each item because
we've set each item in the array to be be a variable.
And then if we just want to pull out one element, the first element, we can dstructure just that element but from the same thing. So instead of
saying const array with XYZ, we can say const with just X. And this will be this will give you just the first element.
Okay.
And if you don't know how many other elements there are, you can use the rest operator, the three dots, to capture the rest of the elements into a new array.
That's pretty cool. So this way we can pull out X, the first element. And then
this will give you an array containing the remaining two items in the array.
And then if you overdstructure, meaning if you add a fourth um item in the dstructured array, but there's only three in the original array, then this
is going to be undefined for that last item. Okay, that makes sense. So we need
item. Okay, that makes sense. So we need to dstructure in the get primary and backup messages.
So it takes an array of messages as an input and then it returns an object with two properties. The first message in the
two properties. The first message in the array primary and then an array containing all the remaining messages.
So that's kind of like what we had here with the three dots thing.
And then if the array is empty, return an object with primary set to undefined and then backup set to an empty array.
Okay. So I think the first thing I'll do is to assume the array has items in it.
So I think we want to do kind of what we have here. So const
have here. So const and then in the brackets I will just say first message, dot dot dot other messages and then
we'll set that to be messages because that's what we're what's getting inputed. Then
inputed. Then we return an object with two properties.
So I guess we'll just do return an object with two properties. Primary
first message and then backups and that will be other messages.
And this should work if messages is not empty. So let's just run this and see if
empty. So let's just run this and see if it at least works for those cases.
Okay, so looks like it is working, which is pretty great. Now we need to write the condition if the array is empty.
So I think maybe we will do if messages length is greater than zero.
Yeah, if it has at least one item then I think we can do this stuff. Need
to indent a little bit more. There we
go.
Okay. So messages length is greater than zero. This otherwise return
zero. This otherwise return primary.
What was it? Undefined backups empty array. Let's try running this again.
array. Let's try running this again.
Oh, still good.
Okay. Um, let's try submitting.
Yay. And once again, I'm just going to check the solution.
Oh, wow. That's like very compact compared to what I did. Okay, so I created a con, you know, first message, comma, dot dot dot other messages. That's similar to
what they did. We both set it to be messages.
That was basically the only thing that was the same.
So they didn't have an explicit other case for checking if the messages are empty or not. So I guess I didn't need
to do this con.
Yeah, cuz if there's nothing in the array then I guess it would be undefined. Primary
would be undefined because it's over overdstructured like that example and then I guess bagus will be added to new array but it would just be like empty.
So, I think I just wrote a lot of extra stuff I didn't need to. But, um, yeah, I think that's it for chapter eight. Yes.
So, that's it for arrays.
Okay. So, we are on chapter nine. We are
a little more than halfway through the course and I feel like I've learned a lot. you know, I didn't learn JavaScript
lot. you know, I didn't learn JavaScript formally, so I kind of saw things in the code because I'd have to make changes in the code, but I never really understood exactly what some of these terms and
principles were, like classes, things like that. So, that's been really nice
like that. So, that's been really nice to, I think, build out a more accurate mental model of what JavaScript really is. Obviously, there's still quite a
is. Obviously, there's still quite a quite a ways to go, a lot more to learn, but so far, it's been a really fun process. So, let's take a look at this
process. So, let's take a look at this chapter here. So we're looking at errors
chapter here. So we're looking at errors and in JavaScript there is a builtin error object which has a message property. So if we create a new error
property. So if we create a new error with this string then we can load that error message um with the message property down here.
Okay. So let's check out our assignment.
So we need to basically create an error and then in front of the actual error message that gets passed through we need to add the error colon text. Okay. So in create
error message I'm going to kind of do what we had in the example here. const
error equals new error and then message should be the parameter.
And then we also want to add the error colon text in front of that message. And I think there's also a
that message. And I think there's also a space. Yeah. So let's do this. We'll do
space. Yeah. So let's do this. We'll do
the uh template literal thing again. So
we'll say error colon space and then dollar sign and then message in curly brackets.
And then I'm assuming we can return it.
So let's give this a shot. Seems good. I
feel like we can also make this a little more efficient. Like what if we could
more efficient. Like what if we could just return new error object like that.
And I think that will do the same thing.
Let's try that. Seems to be working.
Okay.
Nice.
And I can't stop doing this. I just have to look at the solution so I know what like the right answer is. Okay. So they
had what I had before pretty much the same.
So yeah, I don't know if like this is considered better practice like to create an actual const like what I did which is just one line. Maybe it doesn't really matter but they both work so
that's good. All right so we have
that's good. All right so we have learned about errors in JavaScript. Now
let's learn how to handle those errors in our code. So here are a few examples of things that will cause an error. Data
received from an API is not in the expected format. you may have lost the
expected format. you may have lost the database connection or you might have a user who is trying to log in with the wrong password. So what happens when
wrong password. So what happens when errors like this happen um when your code's getting run? Well, if you don't handle your error, then like in this
first example here, we have created a Titan object and then in the next line, we're trying to retrieve the neck thickness property value and then at the end we'll print a done message. But
because this property does not exist, then it's going to cause an error in the program. So what happens is we're going
program. So what happens is we're going to get this error message. But then the program is going to crash. And what that means is it's just going to stop running completely and it's not going to execute
any more code. Meaning this last line here with a done message never gets run.
And we do want to avoid crashing our program whenever possible. So the way that we can do that is to handle our error using something called a try catch
block. So in this example here,
block. So in this example here, these lines are the same code that we had in the previous example. However,
they are now within this try block. So
what happens when the program runs is it's going to try to execute the lines of code and then it's going to, you know, encounter an error here. But
instead of crashing the program, it's then going to jump to this catch block below it. And then then it's going to
below it. And then then it's going to run the code in here. And what we have here is it's printing the error message.
And then at the end of it all outside the try catch block, we have the done message. So now the difference here is
message. So now the difference here is that when it hits this line and you know causes an error, it's going to print the error message. So this is coming from in
error message. So this is coming from in the catch block the printing the error message property and then it is actually going to continue running. It's going to be able to print this last line here.
This is because we have the code that we potentially could cause an error with in this try block. So it's basically an added level of safety so that you know your program doesn't crash. So let's
check out our assignment here. Okay, one
of the calls to get message record. So
we have a bunch of get message record um calls here is throwing a text id not found error change the code to safely make the function calls within a try catch block and then if an error is
raised we want to print that message to the to the console. So I'm going to start just kind of hitting run initially just to see what the result is. Okay, so
we have one, two, three messages printing correctly, I'm assuming. And
then at the end, we have this error text ID not found. Okay, so what we want to do is take this code here and put it into a try catch block like we had up
here. So let's add that in. So try
here. So let's add that in. So try
and then we'll do the autocomplete thing there. And we want to move all the code
there. And we want to move all the code that could potentially cause the error inside the try block. And then we want to print a message if there is an error.
So again, we're kind of just following the template here. Console log
error dot message.
And I think that's correct. Let's just
kind of double check the instructions again. That sounds good to me. So let's
again. That sounds good to me. So let's
now run.
So again, we have the three correct messages and then the end it says text ID is not found. So that seems pretty good. All right, let's give this a shot.
good. All right, let's give this a shot.
Nice. And there's one more block that can be added to the try catch blocks and this is the finally block. So what
happens is that this code in the finally block is always going to be executed no matter what happens even if there is a an error in the catch block itself. Um
which really shouldn't happen. Um so
it's kind of like a last stitch resort.
You know this code will always run no matter what. So in the example here we
matter what. So in the example here we have in the try block the same code that created an error and then we have in the catch block the error message and then
here we have in the finally block it's going to log this string and it's always going to run you know we have our error message here and then it's um sorry in the second line here and then it's going
to run this last line. So let's take a look at working with the finally block.
So here is the cleanup function and notice how cleanup complete this last line here does not get logged. So let's
try running the code with what we have here. Oops, there we go. So this is
here. Oops, there we go. So this is saying error and catch block and that's from the the catch block which is also throwing an error. So it's just kind of like emulating having an error happen inside the catch
block which again shouldn't really happen I think. Um so now we want to add the finally block so that this cleanup
complete message will still get um printed no matter what. So after the catch block finally then we'll move that line of code in there.
There we go. So now it's running again and it does run the cleanup complete message. Okay.
message. Okay.
And there we go. So with errors, so far in this chapter, we have usually had errors thrown implicitly when, you know, we're trying to do something in the code
that causes an error um in JavaScript.
But we can also explicitly create an error message when something happens.
So the way we do that is throw new error. So this will create a new error object and then it's going to throw the error. So make the error
message print.
Um and yeah, we can you can throw anything you want. Not necessarily just an error object, but it's best to stay consistent and then and just use the
error object um to throw an error. So
let's check out the assignment.
So we are integrating with Zer Zerpy which enforces a 70 character limit on incoming messages. Okay, so we need to
incoming messages. Okay, so we need to complete this send message function. And
it looks like we're using an arrow function syntax.
So if the message is longer than 70 characters, throw a new error object with the message. Message is too long.
Otherwise, just return the message. So I
don't think we have to use a try catch block here because there's no code that we're trying to run. I think maybe we just check, you know, the the character
length. So I'm going to try just doing
length. So I'm going to try just doing an if statement. So if message length is greater than so not equal to
but is greater than 70 then throw a new error object. And let's go back up to our example up here. Throw
new error. And then in there we want to have
error. And then in there we want to have our error message. Message is too long.
I don't know if we need a period at the end of that, but I guess we'll find out.
Otherwise, return the message.
So, basically, this is kind of checking I guess we're just checking if the message is too long or not. Okay, let's
give this a shot. All right, looks like it's working.
Nice. Now, when do we want to use try catch blocks? So, this is actually
catch blocks? So, this is actually something that I was thinking about in the last lesson. Um, yeah, errors are not something to be scared of. We just
need to learn how to handle them in our code and we want to handle the errors gracefully and in a way that we kind of expect. It's saying that in some
expect. It's saying that in some programming languages, it sort of tells you up front if you might, you know, want to expect an error potentially in the code. JavaScript unfortunately does
the code. JavaScript unfortunately does not have that kind of functionality.
Um, so how do you know if you want to put any of your code in try catch block? So here are some rules of thumb that we can try to follow.
So if we are kind of managing values or data coming in from outside either from like you know user like filling out a form or something or you're getting data
from an API then you might want to use a try catch block to make sure you know things are formatted correctly and then if they're not and it throws an error then we've kind of handled it correctly.
Another case that we would want to use try catch is if we can recover from the error otherwise just let the program
crash. Okay. And then
crash. Okay. And then
here are some cases where we may not want to use try catch. This is if we are have written some bad code that results in a lot of errors. Don't just wrap it in a try catch block. Instead just fix
the code. And then is it really an
the code. And then is it really an abortw worthy error? And this is actually a good reminder. We can there's some sort of things in JavaScript that
will allow us to check if you know a value is null or undefined. So the
optional chaining operator which I wonder if we could have used that in the um that Titan example where the properties were undefined maybe and then
the nullish coalesing operator. So
checking if something is null or undefined. So those will kind of help us
undefined. So those will kind of help us be able to not always have to use a try catch block for anything that might be undefined. So let's check out the quiz
undefined. So let's check out the quiz here. So which of these is a proper use
here. So which of these is a proper use of a try catch block? Um wrapping every single line of code obviously not.
Handling errors from external input.
That's probably yes. And then covering up your own mistakes. No. So if we want to handle errors from external input,
that's a great case for using try catch.
And that's it. Nice.
And we are now in chapter 10. And we're
working with sets. And I've not worked with sets before, so this will be something new. So what is a set? A set
something new. So what is a set? A set
is a collection of unique values. Okay.
Um, they're fantastic for dduplication and checking if a value exists in a collection. So let's look at the code
collection. So let's look at the code here. Looks kind of like an array. Here
here. Looks kind of like an array. Here
we're creating a new set object and then in parenthesis like this looks like an array and then when we return it, it
will return a set object with the unique values. So originally it was 1 2 3 4 and
values. So originally it was 1 2 3 4 and then 555.
But then when we create it with when we create the set, it's only going to include the unique values. So that's
actually pretty cool. Okay. So, it keeps things unique and we can add and delete values dynamically. Okay. So, in this example,
dynamically. Okay. So, in this example, we're creating a new set and we are manually adding these different strings
and we've added B birth twice. But then
when we return the set after adding all those items, it's only going to return the unique values. And we can also delete values from there if we want.
This feels like something that's like very handy in cases where you need this kind of functionality to like ddup things. Okay, so here's our assignment.
things. Okay, so here's our assignment.
We are unfortunately delivering duplicate email messages, which is always a bad thing. That'll really annoy people. Complete the dduplicate emails
people. Complete the dduplicate emails function. It takes an array of strings,
function. It takes an array of strings, emails. So that's going to be an array
emails. So that's going to be an array and it returns a new array containing containing only unique messages. Okay,
so we need to create a set from the emails array and then creating a set will remove any duplicate emails and then we need to create a new array from
that set and I do not know how to do that but let's just start trying. So
let's just create our set first. So
const will just call this set equals new set and then in parenthesis I think we can add emails the array in in
the set as the parameter. I'm not sure but let's log this and see what it looks like.
Okay, so we obviously failed our test which is fine because we haven't tried returning anything. So I think this is
returning anything. So I think this is the return or this is the what we're console logging set three and then it's telling us the three
items and they are unique which is good.
So we need to figure out how to make an array from this. So I feel like maybe we need to loop through the set items.
So maybe like a for loop. So for let email of set So, let's also console log since I'm
really not sure if I'm doing the right thing here. Console log email.
thing here. Console log email.
So, let's see what that gives us. Okay,
so this is the first console log here.
And then it does look like we are returning each of the individual emails.
So, we are going down the right path I think. So, let me delete that first
think. So, let me delete that first console log. And we need to create a new
console log. And we need to create a new array. So let's do that first at the
array. So let's do that first at the top. So const duped emails. And this
top. So const duped emails. And this
will be an array. So now in our for loop, we will push the individual email that we have looped
through. And let's just delete this.
through. And let's just delete this.
Okay. So now we have our array. Let's
log that. Duped emails. Okay. So let's
run this again.
And this looks like an array to me.
Okay, that looks pretty good.
So, let's just try returning the dduped emails.
And it looks like we passed.
All right. Nice. So, okay. So, that was that was good to know. So, we can loop through a set using our for loop here.
So, in some ways, it's really not that different from an array. It's just a collection of items that you can loop through with a for loop. Obviously, the
the syntax for like adding and deleting stuff is different. But, all right, let's submit this.
Yay.
And just because I'm not sure about the code I wrote, let's check out the solution for this one.
Um, okay. And again, my code was much much longer. So the answer here was
much longer. So the answer here was creating a new const dupe emails for the new set. So that's
actually pretty similar to what I wrote and then oh okay so return and then it's using the I can't remember what this is called
the spread syntax. It's returning an array and it's adding the dduped emails to the array. So you don't this kind of
automatically I guess will add the items in the set to an array. So yeah,
definitely still got a lot to learn, but I do really like having the solutions so I can sort of see where my very inefficient code matches up with, you know, the correct answer. So yeah,
that's good to know. All right, so let's look at these methods that we can also use with sets. So there's an intersection method. It returns a new
intersection method. It returns a new set containing elements that are in both sets. Oh, this feels very like SQLesque.
sets. Oh, this feels very like SQLesque.
SQL I also have a very basic rudimentary understanding of, but you're getting the the intersection kind of like a ven diagram thing where the intersection will only get the parts where the two circles meet.
So that's pretty cool. Okay. And then
there's difference. It returns new set containing elements that are in the first but not the second set. Okay. So
the first in the first set and not in the second set and that's difference.
Okay. So it's like subtracting the second set from the first set. That's
why it's called difference. And then
union which also sounds very SQLesque returns a new set containing elements that are in either. So it's just like it's yeah uniting them. It's like taking all all of the items everywhere. And
then of course it's making them unique.
So yeah, these seem really helpful when you're working with like data I guess.
So let's just look at the quiz now. So
when two sets have a lot in common, which method returns only their shared values? I think that's intersection.
values? I think that's intersection.
Let's just double check. Intersection
returns a new set containing the elements that are in both sets. Yes. So
only their shared values.
Intersection.
Nice. And here's another quiz question.
A difference returns blank. So Oh,
sorry. A. and then b in the in the parameter it returns I think it would be a minus b so values that are only in a and not in b if I think I have that
correct so yeah elements that are in the first set so elements that are in a but not in the second set
so let's see the values in a but not in b let's just double check this values that aren't in both a and No.
Um, the values in B but not in A. I
think it's the values in A but not in B.
Okay.
Like that kind of wording like you can get turned around really easily.
All right. So, I think that's it for chapter 10.
And we are now on chapter 11. And we're
talking about maps. And it seems like maps are another I guess collection of items that you can work with. So maps
are collections of key value pairs.
Okay. So before we're working with like objects and arrays and the types can be you know whatever you want in like
arrays but in maps it's just key value pairs. Okay. And then map keys are
pairs. Okay. And then map keys are unique. So adding a key that already
unique. So adding a key that already exists will replace the value. Oh that's
interesting. And then you can set and delete entries. Okay. So, compared with
delete entries. Okay. So, compared with before in the previous chapter, we were working with Oh my gosh, I can't remember. We're working with sets. So,
remember. We're working with sets. So,
we're working with sets and you could use the add or delete methods. But with
maps, instead of add, we have the set method. So, I feel like that could be
method. So, I feel like that could be slightly confusing, but I guess it makes sense because it's like a set. It's like
a key value set that you're adding to the map, not just, you know, one item.
So, here is our code example. So we are creating a new map object as map and then to the map we are adding using the
set method these different key value pairs and then when we log the map it's going to return kind of like set it says it sort of tells you what the type is
map and then in curly brackets we have the key and then arrow and then the value and then everything separated by a comma.
Okay. And then we can delete items based on the key. Okay, that makes sense. Then
it says maps can be constructed from any iterable. I think that means I'm not
iterable. I think that means I'm not sure, but I think that means things you can loop over like an array. And then
maps are iterable themselves. That means
that you can create a new map from another map. Okay, so original map and
another map. Okay, so original map and we have this blank map here. And then we are adding this key value pair to it.
And then we're creating a copy map which is another map object but it takes the original map as a parameter. And then if we log the copy it's going to return the
same map as we had originally. Okay
let's check out the assignment here. We
are building a phone directory for the support team. We need to complete the
support team. We need to complete the add to phone book function. It takes a phone number and name strings and then a phone book map. So the phone book here
is a map and then it returns a new map.
So let's see. Step one, we need to create a copy of the input phone book.
Let's do that. Kind of like this example here. const and I'll call this phone
here. const and I'll call this phone book copy equals new map object and it will take
phone book. And then so we created a
phone book. And then so we created a copy and then step two we need to add the input phone number as a key with a value name.
So phone bookcopy dot set we're adding a new key value set and it's phone number is the key, name is the value and then
return the resulting map.
Return phone book copy and I this I think this will work. Let's run it. And
looks pretty good. Nice.
Yay. There's like a slight delay. I got
kind of scared. Okay. So, when we're working with maps and map keys, it says in JavaScript, keys can be any type because that's just how JavaScript
works. That's how it rolls. I feel like
works. That's how it rolls. I feel like keys usually are strings or numbers.
But let's I guess let's see what what is possible with JavaScript. So we have a map and to this map we are adding a key
value pair where the key is this which is an array of strings and then the value is a string but then when
we try to I guess get the item in the map with the same key it's returning undefined which seems weird. So let's
see why this is happening. The key is an array but it's a different array than the one we use to set the value. The
contents are the same, but the reference to that object or the array is the same.
So I guess the array that we're using to try to retrieve it is not the same object array that JavaScript kind of
used to create the the key for this new map item. That seems very strange. But
map item. That seems very strange. But
if we use a single named variable as the key, then it does work. Okay, that's
weird. So we're creating our map. We are
creating a new variable greeting key setting it to this array here. And then
if we use the greeting key variable to retrieve the item here, it does return the correct value. Okay, so I'm assuming this probably doesn't or shouldn't
happen very often, but I guess it's an interesting example of like how far you can go with JavaScript to do weird stuff like that. All right, so we are
like that. All right, so we are finishing the create user map function.
It takes an array of user objects. Users
and then each of the user objects in users has a first name and last name property. Okay. So basically we're
property. Okay. So basically we're creating a map. We are adding each of the users in the users array to the map.
And what are we doing when we add them to the map? The key is going to be the first name and last name separated by a space. And then the value will be the
space. And then the value will be the user object itself. Okay. So let's
create our map const. I'll call this user map equals new map. And then we
want to iterate loop over the user objects. So for let user of
objects. So for let user of users I always want to say in for some reason I think that might be syntax from something else but let user of users
and then let's see I guess I'll create a key const. Let's call this username. So this
const. Let's call this username. So this
is going to be our key for the map.
username equals and then the user object contains a first name fame and last name and then separated by a space. So I'm
just going to do this add a space concatenate it with the plus sign. So
user fname space user ln name.
Okay, that seems good. And then we want to add this user to the to the map. So
user map set and then the key is the username that we just created comma and then the value is going to be the user object. So just
user and that seems right.
So let's just return user map. Feel like this code should
user map. Feel like this code should work but you know let's run this and see what happens. Okay looks like it worked.
what happens. Okay looks like it worked.
Nice. And again, I'm just going to check the solution real quick. Okay, I wasn't actually too far off on this one. I just
did the concatenation with the the plus sign instead of using template literal.
And we add different variable names, but I think this Yeah, I think I did pretty good on this one. Okay, so we are looking at map versus object in this lesson. So in JavaScript, we can work
lesson. So in JavaScript, we can work with objects or maps and they are different, but there are some benefits that maps have over objects sometimes.
So let's see. So map keys are ordered in an easy to understand way. Objects are
not. They just have, you know, properties. And then maps are iterable
properties. And then maps are iterable so that you can use for loops on them.
Objects are not without some extra work.
So that's actually feel like this is a really large benefit that maps have over objects. And then maps can be faster and
objects. And then maps can be faster and they do not have any extra properties that you may not want. Okay. So it seems like they accomplish a lot of the same things, but there are some important differences depending on what you're
looking for. So let's look at the
looking for. So let's look at the assignment. So we have a bug. the intern
assignment. So we have a bug. the intern
creating the user map. Set objects with first and last name properties as keys in our user map which is I'm assuming a big no no like we learned in the previous lesson cuz usually you want
keys to be strings and so we can't look up users because the keys are objects.
Okay, so that seems like a pretty bad situation to be in. So let's complete the fixed user map function. It takes a map with object keys mapping to user
objects that hence the name broken map and it returns a new fixed map with string keys. Okay, so there's a lot of
string keys. Okay, so there's a lot of stuff that I think we need to do here.
So I'm just going to start off logging the broken map so I can kind of try to picture what we have to work with
initially. So let's run this. Okay, and
initially. So let's run this. Okay, and
I think this is the result here. So we
have a map with one set I guess you could say and the key is this object and then the value is the user object kind of like what we were working with
before. Okay, so
before. Okay, so let's start. I'm just going to delete
let's start. I'm just going to delete that. Step one, create a new map. So
that. Step one, create a new map. So
const we'll just call this fixed map equals new map. Oops. And I think that's all that we need for that.
So that was the easy part. And then we need to iterate over the entries in the broken map. So four
broken map. So four and I'll say I guess user. I don't know if that's the right
name, but we'll just start let user of broken map.
And then I'm going to console log the user. So I can again see kind of what
user. So I can again see kind of what we're working with.
So there's only one item in the map.
Okay. So this is what we have. So we
have looks almost like an array and the key looks like it is this object here. And
then in the key fame is Aaron last name Jagger and then tags. And then it looks like the value is exactly the same.
Yeah. So it looks like the the key and the value have basically been set to the same thing. And I think this is the
same thing. And I think this is the correct value that we want for the map.
We just need to change the key to not be this, you know, horrendous object. So
what we need to do is we need to somehow pull out the first name and last name properties from the key. So let's see
here. So this thing looks this whole
here. So this thing looks this whole thing looks like an array.
So I'm going to try to or I guess it doesn't matter. I'm going
to try to pull out the first item in what I think is the array. So we're just going to console log user and then zero the the first array item. Let's run
this. Okay, so it actually returned something. So it returned an object with
something. So it returned an object with fname. So, and then again this is like
fname. So, and then again this is like hardcoded. So, let's try fname. Oh, and
hardcoded. So, let's try fname. Oh, and
it returned Aaron. So, we're going to iterate the I inside this let user of broken map loop. So, we'll iterate I at the end and then let's try instead of
user zero, let's try user I. So, let's
run this. Okay. And that did work.
So, we can now know that we can create the key to be user I. So let's say
const user let's just call this key key equals user if name and let's do it differently and use the template literal
here compared to last time and ending back tick and then let's just copy this ln name and then just to check I'm just going to
console log key.
All right. So, let's run this. And it
has the first name and last name, which is great. So, now we can add to the map
is great. So, now we can add to the map the fixed map. So, fixed Whoops.
Fixed map set and then key and then user. I guess
I don't know if that's right because user wants to be the entire thing. I
think this is not going to be correct because if we console log user it's going to be like
the whole messed up thing where the key and the value are the same thing like it's going to be this whole thing which is I think not correct. H. So somehow we
need to pull out let's see pull out the second I guess we can pull out the value of the the correct user object which is
actually the second item in the array.
So I think the value could be user oops user i + one. Yeah, I'm not confident in that at all. But the the
thought is that if the whole thing is an array, the key is a first object, which is the first item in the array, the the value here is the
entire user object. So I'm just going to try this. And let's also console log the
try this. And let's also console log the whole thing. So after the for loop is
whole thing. So after the for loop is done, console log fixed map. Okay.
And then I'm just going to delete that.
So let's try this out.
Okay. So this is the resulting map.
And it does seem like we have the correct key. And the value is I thought
correct key. And the value is I thought this should be correct. This is the entire user object. But it's saying it failed. Oh, because we didn't return the
failed. Oh, because we didn't return the actual map. So let's just do that. So
actual map. So let's just do that. So
return fixed map. Wow. Okay. So I think that
fixed map. Wow. Okay. So I think that worked. Let's try submitting this. Yay.
worked. Let's try submitting this. Yay.
And per the usual, I do want to look at the solution because I'm sure there was a much more efficient way of doing this.
So let's see. So const fix map equals new map. I did that the same for
new map. I did that the same for const. Okay. Key value. So this is the
const. Okay. Key value. So this is the what I was sort of I was sort of working with the array items in like with the user I thing.
But this seems better. So here it's creating a new variable for the key value. So then that automatically pulls
value. So then that automatically pulls out that first you know part of the user and then you can pull out the fn name and last name. Okay. And then they
didn't have to iterate. Okay. A lot to learn here.
But it's kind of interesting that this can achieve the exact same thing as this even though this is like much more inefficient. But I guess that's
inefficient. But I guess that's programming for you.
All right, we are now on chapter 12, which deals with promises. And I have to be honest, I have kind of been dreading this part a little bit just because, you know, I've heard promises are really
hard to understand. And I'm not, you know, really familiar with the asynchronous aspect of JavaScript. I
have done some set timeout functions in the past, but nothing that makes me feel like I kind of understand this aspect of JavaScript. So, you know, let's try to
JavaScript. So, you know, let's try to get through this chapter and we'll see how it goes.
So, we have a little diagram here. So,
let's scoot this over so we can see it better.
So, most code that we've been writing is synchronous code, meaning it runs in sequence. So, you know, basically runs
sequence. So, you know, basically runs in the order that it's written in your code. And in this diagram, looks like we
code. And in this diagram, looks like we have a example of synchronous on the left where we have process A and process
B. Process A starts then it goes to B
B. Process A starts then it goes to B and then process B runs and while B is running process A has to wait for that response and it can't do anything and
then when it gets the response then it can finish running. So to compare with that we have on the right side asynchronous code. So we have the same
asynchronous code. So we have the same two processes. process A begins and then
two processes. process A begins and then it passes it off to process B which begins but instead of having to wait for process B to finish process A can
continue working and do other stuff I'm assuming until it gets the response back from process B and then it finishes running. So let's look at what the
running. So let's look at what the actual code for synchronous code would look like. This is basically the types
look like. This is basically the types of code we've been running. We have
three lines of code logging different messages and they just run in order in the order that they appear here. Now to
compare with that the asynchronous code or async code can run concurrently so at the same time. So we have a main thread
which can continue running. We have
async tasks that are handled outside of that main thread and can run. So one
example of this is the set timeout function. Okay. So how set timeout works
function. Okay. So how set timeout works is we have one example down here in the function. It runs this code and then
function. It runs this code and then there's a comma and then we have a number and that number is the number of milliseconds it's going to wait before it actually execute executes this code.
So that's what set timeout does. It
basically delays starting starting this to run. So when we have these here, what
to run. So when we have these here, what happens is the first console log statement prints because it doesn't have a set timeout. So it just is going to
run synchronously. And then the second
run synchronously. And then the second message is actually going to print second. This one down here, even though
second. This one down here, even though it comes after the set timeout function because it's running while this set timeout is waiting 100 milliseconds. And
then finally, it will run this third line which is last. So let's take a look at the assignment and see what we need to do here. All right. So we are going to kind of practice asynchronous code
using set timeout even though that may not be the best practice for this actual like application here. So what we want to do is we have a bunch of messages
that we want to log and we want them to follow the order that we have here in this list. And then just make sure we're
this list. And then just make sure we're not waiting longer than 2,000 milliseconds or 2 seconds. So let's
figure out the order that we have here. So the first message is starting textio service initialization and that one's here and this one is not in the set timeout
function which means it's going to run synchronously and this will run first and then the others are all in set timeout functions. So we want to add
timeout functions. So we want to add weight times. So the less wait time
weight times. So the less wait time it'll the earlier this message will print. So let's look at the second
print. So let's look at the second message connecting to SMS providers and that's this one down here. And then the wait time is SMS providers wait.
So we'll just maybe do 100 milliseconds.
The next one is configuring message routing. That is message routing weight.
routing. That is message routing weight.
So this one here and this needs to be longer so that it delays longer than the previous one. So we'll we'll add 100 to
previous one. So we'll we'll add 100 to this to get 200.
and then setting up error handling and retries which is error handling weight.
So we'll add another 100 to that and then texio set of complete which is this one here. So we'll add another 100 to
one here. So we'll add another 100 to get 400. So let's run this and and see
get 400. So let's run this and and see if it matches the order in the list here. Okay. And it finished. And it
here. Okay. And it finished. And it
looks like we have starting, connecting, configuring, setting up error handling, and then texio setup complete. So that
worked.
All right.
There we go. All right. So we have a little article to read and then some quiz questions. So you know, why do we
quiz questions. So you know, why do we need async code? By default, all the code we're writing is synchronous. And
it does say that it is easier to keep track of synchronous code which makes sense because if you have let's say you know multiple set timeout functions like we had previously or you're using other
approaches to have asynchronous code running it's a little harder to keep track of where everything is because things may you not be happening in the order that you're expecting. But
sometimes you do need it. For example,
if you need to communicate with other things that aren't just in your sort of codebase.
So if you let's say you have to update your user settings on a website, the browser needs to communicate those settings that you've set to the actual server. And that's going to take time
server. And that's going to take time for your browser to reach a server and then you know get a response back.
Asynchronous code enables sort of everything to happen much quicker because you don't necessarily have to wait every single time you need to wait for a response. So it makes sense why we
need it. You know, it's a little bit
need it. You know, it's a little bit more efficient so you're not just waiting. But which is simpler to
waiting. But which is simpler to understand and work with? Synchronous
code. And let's go next. We got another quiz question. Which kind of code allows
quiz question. Which kind of code allows multiple processes to be run at the same time? That would be asynchronous.
time? That would be asynchronous.
And then async code should only be used on fast computers. Probably
not. Only be used for performance reasons? Probably. and then never be
reasons? Probably. and then never be used and always be used. So those are those are more extreme statements that I think are not true. So yeah, we should only use asynchronous code for
performance reasons is my guess. Most
code that we write as developers is synchronous, meaning that it runs in step one line of code after the other.
For example, this code, I print first, then I print second, then I print third, top to bottom. Asynchronous code on the other hand runs concurrently. While the
main thread continues executing its code, we're able to do other things in the background. For example, take this
the background. For example, take this piece of code. First, we log I print first to the console. Then, we call the set timeout function, which in JavaScript takes a call back and a
number of milliseconds. It will wait the specified number of milliseconds and then call the call back. So we fire that off to happen asynchronously. Then we
immediately print I print second to the console. Now if we wait, we'll see that
console. Now if we wait, we'll see that the final message is only printed after those milliseconds pass. Now the key point here is that the waiting of those
1,000 milliseconds that happens asynchronously. It happens concurrently.
asynchronously. It happens concurrently.
It happens at the same time as we print that second message. Now admittedly,
asynchronous code is way harder to think about. And that's why most of the code
about. And that's why most of the code we write we try to keep synchronous. But
sometimes we need the code to be asynchronous. Imagine that we're running
asynchronous. Imagine that we're running this code in a web browser. And maybe
instead of set timeout, we're using the built-in fetch function to get data from a server. Now the problem is that
a server. Now the problem is that JavaScript is singlethreaded. So if we call fetch to get data from the server, if that fetch call takes 100 or 200
milliseconds, which is very reasonable for a request across the internet, the entire browser will actually freeze up as it waits for that response to come
back because it can only do one thing at a time. So we need asynchronous code. We
a time. So we need asynchronous code. We
need to be able to fire off that fetch request in the background so that the main thread can continue executing.
Without asynchronous code, we would never have performant applications in the browser. But it doesn't just end at
the browser. But it doesn't just end at the browser. The same goes for web
the browser. The same goes for web servers. We need to be able to handle
servers. We need to be able to handle multiple requests at the same time and allow the main thread of execution to keep doing stuff while we're waiting on things like database connections and
external internet requests. Now,
originally all asynchronous code in JavaScript was handled through callbacks, just like the callback that we passed to the set timeout function.
But these days a lot of that asynchronous logic is now handled through the new promises syntax or I should say promise objects. A promise is
just an object that represents two possible states in the future. Its
resolved state which is happy path and its rejected state which means the operation failed. Let's take a look at
operation failed. Let's take a look at this very basic example of a promise.
First, we use the syntax new promise to create a new promise. And that
constructor takes both a resolve and a reject value. Then we're going to use
reject value. Then we're going to use the set timeout function so that this promise will only get resolved in the future. Then based on a random number,
future. Then based on a random number, we're just going to resolve or reject with the strings resolved or rejected.
So this promise object is created immediately and saved into the variable that we've just named promise, which means the main thread of execution can now continue. But then we're going to
now continue. But then we're going to use two different methods on the promise object. The dotn method and the catch
object. The dotn method and the catch methods. The method takes a callback
methods. The method takes a callback that will only run once the promise has been resolved. And the catch method
been resolved. And the catch method takes a call back that will only run when the promise is rejected. So we
provide both logic paths up front and the one that fires will be based on whether or not that promise took the resolve or the reject path. Now,
admittedly, this code looks kind of disgusting, but the good news is there's actually a new syntax now for using promises that makes it a whole lot cleaner and a whole lot less callbacks
to worry about. Instead of catch, and new promise, we use async await. Take a
look at this example. Instead of using and catch, we're now going to just use the await keyword. So, const message equals await promise. that await promise
expression will actually block and wait for the promise to resolve and if it does resolve the resolved value in this case the string resolved will be stored into that message variable. So it
literally sits in blocks and waits. Now
if the promise rejects it'll actually throw an error which is really cool. It
means we can just use the standard try catch error handling that we use in all the rest of our JavaScript code to handle rejected promises. So we use
await and try catch instead of and catch. But how do we create new
catch. But how do we create new promises? Well, instead of using the new
promises? Well, instead of using the new promise syntax, we use the async keyword. When we define a function, we
keyword. When we define a function, we can optionally put the async keyword before the function keyword. And what it does is actually wrap the body of the
function in a promise. So if we wrap a function that returns a string in the async keyword, instead of actually returning a string, it now returns a
promise that resolves into a string. And
if that function ever throws an error, then it actually rejects the promise. So
it's really syntactic sugar for taking the promise API and making it work as more just like standard JavaScript code.
So, promises are sort of the standard way to do a lot of different asynchronous operations in JavaScript these days. And personally, I prefer the
these days. And personally, I prefer the async await syntax anywhere that I can use it. I mean, just compare this
use it. I mean, just compare this example of code that's making repeated fetch requests using callbacks to this code that's using the await keyword. In
my opinion, the await keyword is much easier to follow. All right, let's talk some more about promises. And I did watch this video. I found it very helpful. So I do recommend doing that if
helpful. So I do recommend doing that if you are going through this yourself. So
what are promises? So in real life, so not in coding, promises are a commitment to the future. And they can end either two ways. They can either be fulfilled,
two ways. They can either be fulfilled, meaning the promise is kept, or they can be rejected, meaning the promise is broken, I guess you could say. So the
promise object represents the eventual fulfillment or rejection of a promise.
So those two possible outcomes and then in the meantime while we're waiting for the promise to be fulfilled the code can continue running. So this is an example
continue running. So this is an example of asynchronous code in JavaScript and apparently it's the most popular modern way to write async code. So that's good.
Okay. So let's look a bit more about what an actual promise will look like in the code. So in this code we have a
the code. So in this code we have a random number generation function down here. So it's going to either return
here. So it's going to either return true or false. Then up here is the
promise that we are writing. So
if the random bool is true, it's going to resolve the promise saying resolved.
If it is false, it's going to reject the promise and it will say rejected.
So what looks like we have to do with promises is we create a new promise object and then it can either be
resolved or rejected and then in the function itself inside these curly brackets is this set timeout function which will wait for a th00and
milliseconds meaning 1 second before it either is resolved or rejected.
Okay. So the the new sort of terms I guess I'm learning here is we have the promise itself which is an object and then it has resolve and reject methods I
guess you could call them and these are the two possible outcomes of that promise and in this case in this example the the end status is dependent on
whether this is true or false.
Okay so that I think that makes sense.
Okay. So, how do we use promises? So,
the promise object has then and catch methods. So, I don't know if this is I
methods. So, I don't know if this is I don't know if method was the right word here. Maybe it was, but it has then and
here. Maybe it was, but it has then and catch methods.
So, then is kind of like the follow-up to a promise. So, I guess if the promise is fulfilled and not rejected, it will run code in the then method. And then I
guess if the promise was rejected not fulfilled it will run code in the catch method. So it's kind of like try catch
method. So it's kind of like try catch in a way. So if a promise resolves meaning it gets fulfilled the then function will execute. If the promise is
rejected the catch method will execute.
Okay. So it's kind of like again those two outcomes. These are like the
two outcomes. These are like the follow-ups to if it's resolved or rejected. So it's promise then and then
rejected. So it's promise then and then promise.catch.
promise.catch.
So I'm just kind of comparing it with the example here. Okay. So this looks like this first part handles the resolving and rejecting and then after
those depending on what happens we can follow it up with the dotn and catch methods.
Okay. So there is kind of a lot to uh take in here but hopefully we'll figure things out more with this assignment. All right.
All right. So, in textio, sending messages is an asynchronous process that sometimes takes time to update its status. We're going to simulate this by
status. We're going to simulate this by creating a function that returns a promise which resolves or rejects after a half second delay. So, we can see here in the code, we have this promise
and it will resolve or reject after a half second delay, which is this 500 milliseconds within the set timeout function. So, if we run the starting
function. So, if we run the starting code as is, it's never going to exit because the promise is not resolved or rejected. We can click cancel if that
rejected. We can click cancel if that happens. Let's try that. So it's running
happens. Let's try that. So it's running and then it's just never going to end.
Okay.
So now we need to complete the update message status function that will take three parameters. Message ID, current
three parameters. Message ID, current status, and then is delivered. So
message ID is just a string. Current
status is a string of whatever the current status of the message is like sending. and then is delivered is going
sending. and then is delivered is going to be a boolean. So this should return a promise immediately that after a half second delay we'll do the following. If
the current status is sending and is delivered is true, resolve with this message. If the current status is
message. If the current status is sending and is delivered is false, reject with this message. And then if the current status is anything other than sending, resolve with whatever this
message, whatever the current status is.
And then message ID is replaced with a value of the message ID parameter.
Current status is replaced with a value of the current status parameter. So
using these parameters. So let's begin.
So first I think we need to add the resolve and rejected um parts of the code. So let's go back
up here to the top.
So here we have our promise object and we have the set timeout function and then if something happens that we want
to indicate the promise is resolved we'll do this resolve otherwise reject. So what are those
otherwise reject. So what are those cases? So when will this promise that
cases? So when will this promise that we're working with be resolved? Okay. So
if current status is sending and is delivered is true then we resolve. Okay.
So we'll add if current status is sending and is delivered is true. So
just leave it like that. Then we
resolve. And let's get the syntax for resolving. Um that looks right. Resolve.
resolving. Um that looks right. Resolve.
And then what message do we resolve it with? Here we go. text message has been
with? Here we go. text message has been delivered. Let's copy that. And then I
delivered. Let's copy that. And then I think we need to exchange some of the strings in here with what the parameter is. So back tick textio message ID has
is. So back tick textio message ID has been delivered successfully. So this
should be dollar sign message ID. Okay.
message ID. Okay.
So I think that is done. So then the next one if current status is sending and is delivered is false reject with
that message. So else if current status
that message. So else if current status is sending and is delivered is false. So
exclamation point I think should work then we will reject with
this message here. Oops, no this message here.
And then again we're replacing the message ID with the parameter. Okay.
Oh, and I think I forgot the semicolon.
There we go. All right. And then
otherwise else. Let's check that second case. And
else. Let's check that second case. And
then if current status is anything other than sending which yeah should be else then resolve with this.
So this will be another resolve. So I
guess you can have multiple resolves.
I guess we'll find out. So again, we'll replace message ID. And we also want to replace current status.
Oops, current status. Okay, that was a lot. And I don't think we're quite done
lot. And I don't think we're quite done yet.
Actually, maybe we are done. So let's
look at the code.
So here we have our promise. I'll just
maximize the the code itself. Here we
have our promise. Inside the promise, we have our set timeout function which after 500 milliseconds will go through these different conditions. So depending
on the condition, it's either going to resolve or reject. I think this might have been
or reject. I think this might have been indented a little bit too many times, but I think that's fine. Okay, so I think that's all we need to write. Let's
try running this now.
Okay, looks like it passed. So, I think our promise is working.
Yay. Now, we're going to learn a little more about promises. So, they are the cleanest, but not the only way to handle requests to a server. Another way is
JavaScript's built-in fetch function, which I guess we will cover not in this course. So every time we use a promise
course. So every time we use a promise it's basically going to because we are handling some form of input output. So
we have our code in our codebase but a lot of times you know you might be getting data from an API or you know getting a record from a database or something you could you could even be interacting with you know other physical
devices like a Bluetooth device or something. So you just never know how
something. So you just never know how long it's going to take for those things to complete which is why the asynchronous code with promises will kind of help things run more efficiently
and smoothly. So this question says
and smoothly. So this question says promises are the only way to write async JavaScript that is false. And then the next question what would be considered input output the JavaScript programming
language? I don't think so. An HTTP
language? I don't think so. An HTTP
request I think that's an example. Yeah,
a really slow algorithm. I guess I could be an example. I'm not sure. A function
that adds two numbers together. No, I
think a really slow algorithm is not like an external thing. So, I think the answer for what's input output would be this HTTP request.
Okay. All right. So, let's check out await. And this is the newer syntax that
await. And this is the newer syntax that we can use to, you know, work with promises, but it's like syntactic sugar on top of that. So it's just a little bit more intuitive in terms of you know
what we're writing. So what it is is the wait keyword is used to wait for a promise to resolve. So then once the promise is resolved the await expression
will return the value of the resolved promise. So this is basically to replace
promise. So this is basically to replace the then method um that we had talked about previously.
So up here is the sort of original older syntax using then. So you have your promise, you run the then method. Um it
takes the message parameter and then it's going to if it resolves run this.
So this is if the promise is successful.
So instead of writing all of this, we can instead use the await keyword and we can say con message. So we're creating the message variable as the await promise.
And then if the promise is resolved, we can run that line of code. So it's a lot more simple. We don't have to, you know,
more simple. We don't have to, you know, mess with making an arrow function with curly brackets and stuff like that. So
this does seem better. Okay. And then if the promise is not fulfilled, but if it is instead rejected, instead of using the catch method, we can put all the
code in the promise in try catch blocks.
So this is nice because it looks more similar to, you know, try catch blocks that we've written before in JavaScript.
So here we have the await promise and then we have if it is successful it will run this line of code resolved. Then
this is all in a try block. So this is if the promise is is successful it's going to run the code here. If it is not successful it's going to actually return an error which is why we can then use
the catch block and then if the promise is rejected then we can run that line of code. So basically it's sort of taking
code. So basically it's sort of taking the whole promise functionality and integrating it into you know the existing JavaScript syntax of try catch
by using the await. So this seems a lot cleaner than what we would have to write with you know like the promise code here. So let's check out the assignment.
here. So let's check out the assignment.
We're working with the update message status function like we had done before.
It takes a message ID current status and then is delivered. So in this assignment we are running we're executing the update message status function using the
following parameters and then we want to await the return promise and then save the result value into a variable called message and then it's already going to
log that message. So what do we need to do? We need to let's look at the I guess
do? We need to let's look at the I guess we can look at the syntax here. It
didn't say try catch. So maybe we'll just start off with the const
message equals await um promise.
I wonder if we need to create the promise first cuz this doesn't exist yet. So maybe create the promise
yet. So maybe create the promise variable and this will be running this function
with the parameters. So message id is m123 current status is sending and then is delivered is true. Okay so this will be
the promise and this function returns a promise and then we're setting message as the await promise. So I think that's right.
promise. So I think that's right.
Okay, looks like it did work. And
there's a extra thing here. For extra
difficulty, try combining lines one and two into one line by awaiting the output of update message status. So I guess instead of promise, we can maybe set the
message to be await and then you know this function because it is returning a promise already. So we don't need to
promise already. So we don't need to necessarily create a whole new promise and then you know work with that. So I
think this should also work.
Okay, that looks pretty good. Yeah,
let's try submitting this.
Nice. All right, so we have a little quiz here and we're talking about then versus await. So I guess old syntax
versus await. So I guess old syntax versus newer syntax. And this is telling us that even before then existed be way before await existed the only
thing you could do for asynchronous coding was to use callbacks and a callback function is a function that gets handed to another function and
then that later function calls back to that earlier function. So one example is set timeout. So here we have a call back
set timeout. So here we have a call back function and then later on we are using the set timeout function and then we're going to run the call back function you
know with after the 1,00 millisecond delay. So the set timeout function later
delay. So the set timeout function later goes back and runs the call back function after the the timeout is finished. And that's basically how you
finished. And that's basically how you can tell that something asynchronous is complete from what I understand. So this
is basically a reminder that while the then syntax is easier than the callback syntax,
the newest async and await syntaxes are the most simple and easy to use. So
basically oldest is callbacks which is the hardest. Then we had the then syntax
the hardest. Then we had the then syntax which is a little easier and then we have async and a weight which is even easier. So yeah, which one is easier to
easier. So yeah, which one is easier to understand? So this is the the then
understand? So this is the the then syntax with promises and then this is the newer syntax with await. Yeah. So
you know fewer fewer curly brackets is generally a good thing and I guess there's still a lot of legacy code that uses the then method. So that makes
sense. Things always progress. So here's
sense. Things always progress. So here's
our quiz. Blank is generally the cleaner syntax. I'm going to say a sync aait is
syntax. I'm going to say a sync aait is cleaner than the promise and then and then async can be used in place of blank and await can be used in place of
blank. So async is in place of creating
blank. So async is in place of creating a new promise and await is in place of
the then method. So new promise and then yeah.
Yay. All right. I think that's all.
Yeah, that's everything in chapter 12.
So, good job everybody.
All right, so we've now gotten to chapter 13 and we're going to be talking about the event loop in JavaScript.
Starting with how JavaScript is singlethreaded, which we have sort of talked about before. You know,
JavaScript can't handle simultaneous multiple processes at the same time. As
we can see here, some other languages can do this multi-threaded thing.
Um, but JavaScript kind of makes up for that because it can do asynchronous processing. So even though it has a
processing. So even though it has a single main thread, it can send things off and wait for a response. And while
it's waiting for that response, it can, you know, start other processes. So in
that way, it is able to be much faster than you might think considering it only has a single thread. JavaScript is
famously single threaded. You've got an 8 core processor. Honestly, pretty cool, but doesn't really matter that much if you're running JavaScript. The main
JavaScript thread of execution can only do one operation at a time, meaning that your eight cores won't all be able to run at the same time, utilizing the full power of your CPU. So, you might be
thinking, well, if JavaScript is single threaded, it must really suck at doing lots of things at the same time. But
that's actually not true. JavaScript is
quite good when it comes to asynchronous programming. And the best way to think
programming. And the best way to think about that is while JavaScript's not good at doing many operations at the exact same time, it is really good at
firing off things to be done in the background and then handling them as sort of the inputs from those different tasks come back to it. In other words, it's really good at orchestrating a
bunch of stuff that's happening, but not at doing all of that stuff itself. An
even more precise way to think about it is that JavaScript is really good when the tasks you're doing are IObound, input, output bound, things like making
network requests, accessing databases, reading from files because it can send the requests for that data out and then sit there and wait for the responses to come back without blocking. It's not
very good when the operations you're trying to do are CPUbound, like lots of mathematical or logical operations all at the same time again because it can only do one at a time. Now, I do want to
point out that JavaScript again is really good at this asynchronous stuff.
this stuff where it's firing off a network request and sitting and waiting to the point where it actually outperforms a lot of languages that do have support for multi-arting languages
like PHP, Python, and Ruby in a lot of benchmarks where the operation is IObound. But it will usually be
IObound. But it will usually be outperformed by languages like Java, Go, C, and Rust when the problem at hand is CPUbound or very computationally
expensive. And the reason it's so good
expensive. And the reason it's so good at this async stuff is that by design, JavaScript is nonblocking. Take a look at this Python code. First, we import the time library. Then, we print start.
Then, we wait for 2 seconds. We print
middle. We wait for 2 seconds again. And
we print end. Now, look at this JavaScript code. We log start to the
JavaScript code. We log start to the console. Then, we use the set timeout
console. Then, we use the set timeout function to defer a function or a call back for 4 seconds. At the end of 4 seconds, we're going to console.log end.
Now, that's been deferred. We're going
to immediately log middle to the console. So when we execute this one,
console. So when we execute this one, it's going to immediately print start, then middle, then wait 4 seconds, and then print end. Now, the reason we had to write the JavaScript code in this
weird way with a callback function is because JavaScript can't block. In the
Python code, each of those times sleep function calls blocks the main thread.
It just sits there and waits. JavaScript
won't allow this to do this on the main thread. JavaScript uses callbacks and
thread. JavaScript uses callbacks and promises. It's asynchronously shoving
promises. It's asynchronously shoving stuff out of the way so that the main thread can keep going and keep processing stuff. And the results of
processing stuff. And the results of those deferred or asynchronous tasks are going to come back later for us to process, but only when we're ready to process them because they've been completed. In some ways, you could maybe
completed. In some ways, you could maybe think about it like it's good at multitasking and delegating even if it can't itself process and compute multiple things at the same time. So
things that JavaScript are good at is things that are IO input output bound like if you're sending things off and receiving things from like an external
API or database or something like that versus CPUbound processes like heavy calculations JavaScript will struggle with because all that's like in its own
server as opposed to other languages like Python, Ruby or PHP which are multi-threaded. So, I guess it kind of depends on what you're trying to
do in your web app or whatever and that can kind of determine what program what programming language might be best for you.
So, let's check out this little quiz here.
JavaScript handles many network requests despite being singlethreaded by nonblocking is my guess.
Yeah, cuz it's not multi-threaded. So
previously we had talked about how JavaScript is singlethreaded.
Now we're going to talk about how JavaScript is non-blocking. So here's an example and we are comparing it with Python. So Python there is a sleep
Python. So Python there is a sleep function that we're using here. So
what's happening is it's going to print start. It's going to wait for 2 seconds.
start. It's going to wait for 2 seconds.
Nothing's going to happen while it's waiting. It's just waiting. Then it'll
waiting. It's just waiting. Then it'll
print the middle message, wait for another two seconds, and then print the end message. So it is blocking in
end message. So it is blocking in Python. So if we compare that to
Python. So if we compare that to JavaScript, we could try to do the same thing, but instead of sleep, we use the built-in set timeout function. But what
happens here is that it prints the start message. Then it cues up the end message
message. Then it cues up the end message to execute after 4 seconds. And you
might think that it'll wait 4 seconds, print end, and then print middle. But
because JavaScript doesn't block while it's after it's queued up the end message while it's waiting it's going to print the middle message and then after 4 seconds it'll finally print the end
message. So just a different way of
message. So just a different way of operating. So let's check out the
operating. So let's check out the assignment. We want to block execution
assignment. We want to block execution similar to how the sleep function works in Go and I'm assuming Python. And we
can do this in JavaScript, but we have to kind of adjust the set timeout function. So what we want to do is we
function. So what we want to do is we have a sleep function which takes a parameter ms for milliseconds to tell us how long we want to delay. Then we have
to use a promise that will resolve after the set timeout function. So this will kind of make sure it actually gets delayed. So let's try this. So the sleep
delayed. So let's try this. So the sleep function has to return a promise. So
return new promise and then I think we have to do something like this where it has resolve as a parameter and we'll use arrow function.
So this is the promise and then inside the promise we want to run the set timeout function and then set timeout
we'll also try an arrow function and then in the set timeout function I think this is right ms for the delay
and then inside the set timeout function after the delay it's going to resolve the promise so resolve like that and saying set timeout out
resolve MS should be the parameters. I'm
not sure.
Why? Okay, let's just try this.
Okay, that doesn't seem good. I think
that's taking too long. I'm just going to try removing this.
Okay, and that passed. So, clearly I'm not doing something correctly. Okay, I'm
just going to try submitting this cuz I don't know what else to do. I feel like I don't know enough to fix that.
Okay, it did work. So, let's check out the solution and see what I didn't do.
Okay, so their solution is much shorter.
So, they did return new promise with resolve, which I did too. And then I guess they didn't need curly brackets maybe because it's only one line. So,
you don't need curly brackets for that.
And then set timeout. Okay, so this is just maybe a more compact way of running that because in the set timeout function, it's only running the resolve function
as the callback. I think I'm not super confident in that, but maybe because it's only running this function, you don't have to do the curly brackets. So
like the curly brackets kind of you need them if you have multiple lines of code.
So because the promise and set timeout only have one sort of line, you don't need curly brackets. So I
guess this is just kind of the classic way of writing a sleep function in JavaScript. So it did the same thing as
JavaScript. So it did the same thing as what I did. Obviously, it's more efficient because it's just one line. So
yeah, interesting. So we know that JavaScript has a single main thread and that that thread is nonblocking. So that
kind of begs the question how do all these asynchronous tasks actually get completed and the answer is the event loop. Now there are two important data
loop. Now there are two important data structures to understand before we can really talk about the event loop. The
first is the call stack which operates very similarly to other languages call stacks and the second is the task Q or sometimes called the message Q. Let's
start with the call stack. Whenever a
function is called in JavaScript, its execution context or frame is pushed onto the call stack and then when the function returns, it's popped back off of the call stack. For example, take a
look at this code. Start job calls work on job which calls finish job. And in
the middle of the finish job call, we've pushed three stack frames onto the stack. But once finish job finishes, its
stack. But once finish job finishes, its frame will be popped off. And then work on jobs frame and then start jobs frame.
So we kind of get these stacks of frames as we get nested function calls. Now
unlike the call stack, the task Q is a Q. It's last in first out, not first in
Q. It's last in first out, not first in first out. And whenever an asynchronous
first out. And whenever an asynchronous operation completes, that operation's callback, the thing that we want to do upon completion is pushed into the task
queue. So that means our main thread can
queue. So that means our main thread can start many different asynchronous operations at the same time and as they complete their callbacks are just added into this task Q. So then of course the
next question is when do the task Q call backs actually get to run. That's what
the event loop takes care of. The event
loop is a loop that's always running and its rule is if there are frames on the call stack it's going to process those first. But once the call stack is empty,
first. But once the call stack is empty, it will check the task queue and if there are tasks in there, it will take one out of the queue and push it onto the call stack and then that task will
run just like any other normal function.
So in other words, anytime the call stack becomes empty, it can start taking work from the task Q. So using the same example from before, let's see what
happens if we add a set timeout with a 0 millisecond delay to the start job function. When we call start job, its
function. When we call start job, its frame is going to get pushed onto the stack and that set timeout function is going to immediately defer its call back with a timeout of zero. So it's
immediately added to the task Q. Now the
problem is there's something on the call stack. So the task Q can't get processed
stack. So the task Q can't get processed immediately. So then work on job is
immediately. So then work on job is called and its frame is pushed into the call stack. Then finish job is called
call stack. Then finish job is called and its frame is pushed onto the call stack. Finally, all those functions
stack. Finally, all those functions return one by one and the deferred call back from the task Q isn't called or I should say isn't pushed onto the call
stack until all those functions return.
And this can be confusing because set timeout 0 milliseconds feels like we should be calling this call back immediately, but that's not how the event loop works. So, it's not too complex. You just kind of need to
complex. You just kind of need to understand what these two data structures are and how they interact with each other. Now, it does get just a little bit more complex because there actually is a second queue and it's called the microtask Q. And fairly
simply, it's called the microtask Q because it's meant for microtasks, smaller tasks. And importantly to note,
smaller tasks. And importantly to note, the callbacks from promises like the callbacks, they're actually placed into the microtask Q, whereas a call back given to set timeout, for example, just
goes into the regular task Q. And the
rule with the microtask Q is basically just that the microtask Q gets priority over the regular task Q. Take a look at this example. We've defined a function
this example. We've defined a function main. The very first thing it does is
main. The very first thing it does is print main start. Next, it creates a timeout for a callback function and defers it for 0 milliseconds. And that
one just prints macrotask one finished.
We're using macrotask to refer to the the larger tasks, the non-microtasks.
Next, it resolves a promise with two different callbacks. one that prints
different callbacks. one that prints microtask one finished and one that prints microtask 2 finished. These are
the callbacks that will be pushed onto the microtask Q. Finally, it prints main end. And the output is really
end. And the output is really interesting. Main start is printed
interesting. Main start is printed first, of course, and then main end is printed. And that's because both of
printed. And that's because both of those operations happen in the main thread before we even go to either of the task cues. Now, this is the important part. Remember how I said set
important part. Remember how I said set timeouts tasks go onto the macro Q or the the regular task Q? Well, that's
true. The problem is we then immediately push two things into the microtask Q.
And the rule of the event loop is that it will pull callbacks from the microtask Q before the regular task Q.
Now, I just want to say usually when you're writing JavaScript code, you don't have to worry too much about how all this works. But it's at least important to understand from a high level what happens when you're deferring
these callbacks because occasionally you'll run into a hairy bug that is seemingly fixed by putting in a set timeout with zero. And it's important to understand why those interactions work the way they do. Now, there might be one
final question that you're wondering, which is if JavaScript's singlethreaded.
What logic is actually running the waiting time for something like set timeout or in the case of a fetch request actually making the request in the background? Cuz clearly it's
the background? Cuz clearly it's happening at the same time. And the
answer is external APIs. In our
JavaScript code, we're allowed to call these set timeout or fetch functions that are provided us by the runtime. But
the implementations of those functions aren't just plain JavaScript that's running within our JavaScript runtime.
They're running in the greater context of the system. And they're not constrained by singlethreaded. They're
actually typically multi-threaded processes often written in languages like C or Rust or Zigg in the case of bun. And once that external code has
bun. And once that external code has taken care of whatever it was going to do, whether it's a database call or a network request, the result of that operation is then wrapped into a call
back and placed into the task queue so that our single threaded JavaScript code can pick up the results and carry on and use it. All right, so we're going to I
use it. All right, so we're going to I guess learn a little bit more about how JavaScript manages to run certain tasks in the background while also having a main thread going. And the way that can
happen is with something called the call stack. So every time a function is
stack. So every time a function is called it gets added to the top of the call stack and then when the function returns it will get taken off the stack.
So let's look at this code example here.
So we have three functions start job work on job and finish job. And then we begin by calling the start job function.
So when the start job function gets called, it gets added to the call stack down here. So first it's empty and then
down here. So first it's empty and then we add start job. Then in the start job function itself, we log job started and then it also is calling another function
work on job. So then work on job gets added to the call stack on top of start job. And then the same way work on job
job. And then the same way work on job has a console log message and then it itself is going to call another yet another function finish job and then finish job will get added to the top of
the call stack. Then it's going to finish running the finish job function first. So it gets removed from the call
first. So it gets removed from the call stack. Then it kind of keeps going down
stack. Then it kind of keeps going down from top to bottom. Then it finishes work on job leaving just start job. And
then it finishes start job. And then the call stack is again empty. Let's check
out the quiz here. Um, the JavaScript call stack works by I think pushing function calls and popping them off when they return. Yeah. So, those other other
they return. Yeah. So, those other other ones don't seem like the answer. So, I
think it's this one.
Okay. So, we learned about the call stack, which is how JavaScript kind of orders running synchronous tasks.
However, you know, we've been talking about asynchronous code like set timeout functions and things like that. So, how
does that factor in to this event loop thing? So it's telling us that things
thing? So it's telling us that things that are asynchronous will get pushed off in something called the task Q. So
now we have the call stack which is what is currently getting processed. Then now
we have the task Q. So
it looks like anything asynchronous will get added to the task queue and you work on everything in the call stack first and then when the call stack is empty
then you'll add tasks from the task queue. So, it's kind of like um a canban
queue. So, it's kind of like um a canban board where you have all the things you're currently working on and then when that's empty, you need more things to work on. So, you then pull from your
your backlog or to-do list to add into your currently working on list, which is the call stack. So,
let's take a look at this code here. So,
here we have the sort of job functions that we had in the previous lesson.
However, now in the start job function, we have a set timeout function.
So, we need to figure out what's going to run first. Well, start job is running first. And you might think that because
first. And you might think that because the set timeout delay is only is zero, it would log this first. But that's not the case because set timeout is async.
So this will immediately get pushed off to the task queue to do later on after all the synchronous tasks have been run.
So that means in start job it's going to log job started then it's going to run work on job it's going to log the working on job message and then it's going to call finish job and then finish
job it'll say job finished. And then
after that all the synchronous tasks are complete. So the call stack will be
complete. So the call stack will be empty and then it's going to pull from the task Q which is this set timeout function with the hi I'm async message.
So you can see here this is what actually happens. Job started working on
actually happens. Job started working on job finished and then hi I'm async at the very end. So I guess it's a good way to sort of separate things. So anything
that's asynchronous means it's going to be pushed off till later. So it gets pushed off to this task Q. Meanwhile,
we'll work on the current things to do in the call stack. And then as we have the call stack emptied out, then we can get more tasks to do from the task
queue. Let's check out our assignment
queue. Let's check out our assignment here. So, there's a bug in our analytic
here. So, there's a bug in our analytic system. Um, an engineer tried creating a
system. Um, an engineer tried creating a deferred log using set timeout, but it always logs success even when it fails.
So, that's not good. So, we want to use set timeout in the correct place. So
let's check out our code here. So what
we got going on here is we have a process messages function and we are um setting a success variable to true by
default. We're going to log a processing
default. We're going to log a processing messages message. Then it's going to
messages message. Then it's going to call the finaliz job function with the success variable which I think is going to be true which this is kind of a red
flag here. It's like running this
flag here. It's like running this function with this variable that we just made, but it's not going to be able to change to not true. So that might be one
of the reasons that this is happening here. So let's just keep going. We have
here. So let's just keep going. We have
an if condition. So if messages are less than zero or more than 100, it should fail with different messages, either too few or too many. And then
console log doing more stuff. And then
here's the actual finalized job function. So it's taking in the success
function. So it's taking in the success variable and then the same messages.
Then it's going to declare a message variable. So if
success is true, it will say processed messages successfully. If it is not
messages successfully. If it is not true, if it's false, it'll say failed to process messages. And then here's where
process messages. And then here's where the set timeout function is where it will log the message.
So it'll log one of these two messages.
Okay. So let's run the code just as is.
So it says processing 42 messages.
Process 42 successfully. That seems
correct because based on the conditions that we were looking at success is between zero and 100 messages.
Then in the next test we have processing messages negative one which should fail.
And it is printing the invalid data message, but it's still saying that it's successful. And that process negative
successful. And that process negative one successfully is coming from the finalized job function. This message
here. So that tells us that finalized job is, you know, not getting the correct value of success. And then the
last example, 9,0001 messages is in the same way getting the success message.
So my guess is that we want to take this timeout and remove it from here and we probably want to move it up to the top
um and run finalize job within the set timeout function. So let's try doing
timeout function. So let's try doing that um comma zero.
Okay, I think I got all my parentheses and curly brackets. Okay, so now we have a set timeout. So finalized job is going to run after the rest of all this stuff
runs. So I think when finalized job does
runs. So I think when finalized job does fire, it will have the correct success value based on our if conditions down
here. So let's try running this.
here. So let's try running this.
Okay, so 42 is successful. Negative1 is
now loading the failed message and then 9001 is also loading the failed message which is correct. So, I think we are good. Let's try submitting.
good. Let's try submitting.
Nice. I'm also just kind of curious. I'm
just going to take a look at the uh solution here. See how close I got.
solution here. See how close I got.
Okay. So, it looks like yes, we did the set timeout function in the same place for finalized job.
And yeah, I think we basically did the same thing. So, yeah. Nice. All right.
same thing. So, yeah. Nice. All right.
So, we have the call stack and then we have the task Q. Now, we're also going to add something called the microtask Q to this whole event loop thing. So,
similarly to the regular task Q, the microtask Q is something where it'll keep track of tasks to be processed, you know, later on, kind of pushed off. But
the microtasks are going to be prioritized before the regular tasks, I guess, the macro task, you could say.
And the reason that this is kind of important for us is promises are considered microtasks. So what happens
considered microtasks. So what happens is you have your regular task Q and then you have your microtask Q. Anything in
the microtask Q is going to be processed before getting to the regular task Q.
And one interesting thing is that microtask can add more microtasks to the queue and those will still get executed before the next macro task. So basically
there's two sort of tiers of task cues.
The microtask Q is has top priority and then the regular task Q is after that.
So let's look at this code example here.
All right. So we have a main function which is this whole thing here basically. So in the main function we
basically. So in the main function we have a main start message. Then we have a set timeout function saying macrotask one finished. Then
after that we have a promise that's resolved and it has two tasks in it.
Microtask one finished and microtask two finished getting logged. So based on what we just learned because the microtasks promises will get resolved
for the macrotasks that means that we start off with the main start because this is synchronous code. It's not
asynchronous. Then the next thing that gets logged I think is going to be console log main end maybe and then we'll do the microtask which is
microtask one microtask two and the last thing will be macrotask one so let's see if this was right yeah so main start main end microtask one microtask 2
macrotask one so I guess it's just a matter of knowing what order things will get executed in um that's kind of the purpose of these different task cues
All right. So in our assignment here, we
All right. So in our assignment here, we want to fix the process analytics function, this one here, by using a promise to concatenate some a string
processing and then the data to the final analysis before it's finished. So
let's start off by just running the code as is and seeing what happens. Okay, so
this fails. So right now it's just printing analyzing dot dot dot and then finished. But it didn't add the data
finished. But it didn't add the data like we need to do here. analyzing dot
dot dot processing whatever the message is. So
let's check out our code. So we have a new promise here um which resolves the analysis. Then we have a it's in a set
analysis. Then we have a it's in a set timeout function by the way. And then
there's another set timeout function with zero delay compared to the 100 micro millisecond delay earlier. And
then we are adding analyzing. So it's
kind of what's happening.
What we have now is just analyzing and then finished which gets added here.
So what I think we need to do is here we want to add a new promise to concat concatenate this processing data
string before this runs. So let's go back up to the code example here. So I
think we'll just sort of do the same thing. So promise resolve uh then arrow
thing. So promise resolve uh then arrow function curly bracket.
Okay. And here is where we want to concatenate. So analysis concatenate
concatenate. So analysis concatenate and then let's copy that string that we need. Processing data.
need. Processing data.
I think we want a space before the dash.
And then we'll use our template literal to add in the data which is coming from here. Okay. So now
that we've added the promise, theoretically this should fire before the set timeout tasks fire.
So let's try running again. It looks
like it passed. Pretty good. All right.
Nice. Alrighty. So let's talk about concurrency.
So so far we've learned about JavaScript that it is singlethreaded. It only has one thread in the runtime. The main
thread cannot be blocked by asynchronous tasks. And to handle those asynchronous
tasks. And to handle those asynchronous tasks in addition to the main thread, we have another task Q that goes, you know, sort of while the call stack is running.
So how do those things work? So for
things like set timeout function, what makes this get delayed by a th00and milliseconds?
And the answer apparently is external APIs. So these things that we're using
APIs. So these things that we're using for asynchronous stuff like set timeout, fetch, add event listener, these are actually run by external APIs that you
get from either your browser in the case of you know JavaScript that runs in the browser or could be node, deno or bun.
So this works and this enables the JavaScript runtime that you're actually running to be singlethreaded, but these external APIs
can kind of go in the background. So
that's kind of how it sort of all ties together, which is pretty cool. All
right, so let's look at this quiz.
Asynchronous callbacks are pushed into the task Q by the microtask Q, no call
stack, no fairy dust, and external APIs.
So external APIs it is. And there we go.
All right. So we made it to chapter 14.
And in this chapter we're going to talk about JavaScript runtimes. So this is where JavaScript runs. And you know originally JavaScript was made to run
just in the browser. So the browser is one runtime where we can run JavaScript.
And then there's other runtimes like Node.js JS which allows you to run JavaScript sort of on the server side and here are some other ones a web
worker within a browser and then dino and bun which are similarly to no they're kind of newer versions that I think do the same thing where you can run JavaScript kind of on the server
side.
So which one do we want to use? Depends
on what you want to do. For a lot of it, we're going to be writing JavaScript for websites and it could just be something that happens in the browser. But if we want to do like backend JavaScript, then
that would be when we need to use like Node or one of the other other options.
So let's check out this quiz here. Which
one is not a runtime for JavaScript?
NVIDIA probably. I think you know they just make chips. Node is a runtime.
Chrome is a browser. So henceforth it's a runtime. Bun is also a runtime. So
a runtime. Bun is also a runtime. So
Nvidia is not a runtime. All righty. So
we're going to do some stuff with NodeJS on our command line. And it's similar to in Python you can run Python and then the name of the file to run the Python
script. With Node, you can type in node
script. With Node, you can type in node and then the name of the file and we can run that file. So that's what we're going to be doing in this lesson. And
there are some things that you need to that we need to install before we can do all this. So we need to have node
all this. So we need to have node installed. Also I'm using Windows. So I
installed. Also I'm using Windows. So I
am using WSL or Windows system for Linux to run Linux on my computer.
Then in addition to Node, we also want to have Node version manager. So this
lets you run multiple different versions of Node on your computer. And then
after that, we're going to work on this assignment. So we want to create a new
assignment. So we want to create a new directory called Heer and CD into it which I actually already did and then install nvm which I also did and then we
also want to use this version by creating the nvm rc file and then we can type in nvm use in our command line to use that specific
version.
So I have done all these things so let's check and make sure it is using the right version. So here's my terminal. So
right version. So here's my terminal. So
node version 2170. So that seems correct. So now we
2170. So that seems correct. So now we want to go into that directory heer and we need to create a main.js file. So
I had to look up some Ubuntu commands, but to create a file you can use touch and then the name of the file main.js.
And then we want to I guess edit it. So
nano main.js.
And we just want to log hello world to the console. So
the console. So and then let's save.
Okay. So to run this file, we should be able to do it with node main.js.
And it is indeed logging the correct message, which is great. The other thing we need to install is the boot.dev CLI, which I did do already. I think we're good on that left side. There's some
more things here. So this is to run and submit our code in the command line versus how we've been doing it in the browser. So let's run this.
browser. So let's run this.
And then I guess I did sort of manually test it, but let's run this.
And it looks like it is good. So now
let's submit.
Nice. That's actually really cool how it like links up to your boot.dev user account. Okay, so I think we're pretty
account. Okay, so I think we're pretty good. All right. So, we're going to be
good. All right. So, we're going to be doing stuff with Node. And that means that we're also going to be working with npm or node package manager. So, what
npm is is it's just a huge library of software that people write code for and they add their packages of software to this registry and then it makes it available for other people to download
and use for their own projects. So,
there's a lot of really helpful tools, both small and gigantic things like React, um, that you can get from npm.
So, we're going to be working with npm a little bit. And what we want to do is we
little bit. And what we want to do is we want to go into our command line and we're going to run npm init. So, this will
initialize a project when you're starting a new project. So, npm init.
And according to the note here, we can just say use the flag Y. And this will basically say yes to all the questions and accept default values. So what this
does is it's going to create a package JSON file. And this is going to let us
JSON file. And this is going to let us kind of configure our project.
So here's what is in our package.json
file. So now if we look in our directory, we have the main.js file that we added initially. And now we also have this package JSON file. So let's check out what we need to do for the assignment here. So we want to edit the
assignment here. So we want to edit the main.js file so that it prints moo to the console. So let's do that. nano
the console. So let's do that. nano
main.js.
So instead of hello world, we'll say moo and then save.
Why can I not save? There we go.
And edit the script section of our package.json file. So let's edit the
package.json file. So let's edit the package JSON file and this is what was generated when we ran npm init. So the script section is
over here.
So remove the test script. Add a new script called start that runs node main.js. So
main.js. So
I'm just going to reuse the same line.
Add a new script called start. And what
it does is it's going to run node main oops node main.js. And hopefully that is the right way to do that. Okay. And
that's it. So let's save.
Then we want to run npm run start. So
this will run that start script that we added.
npm run start.
So it successfully prints the moo message to the console. Okay. Okay. So I
think that is everything we need to do for this assignment. So now we need to run and submit our CLI tests. So run
and I think that's fine. Next is
submit.
And looks good. So we've been working with JavaScript in the boot.dev dev integrated IDE as well as a little bit on the terminal. And now we're going to work with it in the browser on an actual
website. So how does that work? Like how
website. So how does that work? Like how
can we use JavaScript to you know do things on a website? Well, this is where the DOM comes in. So the DOM stands for document object model. And what happens
is when you open an HTML file like index.html HTML in the browser. The
browser is actually going to create a representation of that HTML document or file and this is the object that JavaScript can interact with.
So here's an example. So we have this sort of mini website here as a head tag with a title. It has a body tag where the content goes. And in the body we
have an H1 tag with this ID of main heading. We have two paragraph tags. And
heading. We have two paragraph tags. And
then we have a button at the bottom with an ID of join button. So when we load this HTML file, the browser creates this global object called the document. And
this is what we can use um in JavaScript to affect things and change things on the actual website. So one of the things that we want to try on this website is we want to change the text of that H1
tag. And we also want to alter the
tag. And we also want to alter the styles of the two paragraph tags when we click the join the fun button. So the
way we do that is in our JavaScript we want to create a function called on join click. So this is basically the same
click. So this is basically the same kind of stuff we've been doing the whole time. We are creating functions and then
time. We are creating functions and then inside the function this is where we have some kind of new stuff that we haven't really covered before. The way
that JavaScript can sort of target elements in the HTML is by using that document object that was created and then we can use this method get element
by ID and then it takes a parameter of the actual ID value. So this main heading is the ID that the H1 tag has.
And then once we target the H1 tag with this selector, we can then change the text content property which affects the text content of the H1 tag.
So this is what we'll change. So this is one thing we can do with JavaScript. You
know, we can change properties of elements. And another way that we can
elements. And another way that we can another thing we can do is by changing the styles. we can actually change the
the styles. we can actually change the CSS of elements using JavaScript. So
what we want to do is for the paragraph tags we wanted to change the text color.
So in CSS you can you can control the text color with the color property. And
here's how we can do that in JavaScript.
So first thing is we want to affect all paragraph elements. So the way we do
paragraph elements. So the way we do that is we're creating this um variable paragraphs and we are getting all the paragraph elements with document get
elements by tag name and then this is the actual tag the P tag or paragraph tag. So this will then create kind of
tag. So this will then create kind of like a grouping of all the paragraph tags on the website. So now we need to loop through all the paragraphs and for
each one we want to set the color to red. So we have our for loop here. So
red. So we have our for loop here. So
const p of paragraphs. So for each individual paragraph tag, we can change the style with this style property. And
then we can add the name basically of the CSS property that we want to target and change. So color is going to be the
and change. So color is going to be the CSS color property. And it's not always a one one, but usually the the wording is very similar. I think using camelc
case for multiple words. So here we are changing the style color to red. So what
happens here in the website is it'll I think add an inline style in the actual DOM for each of the paragraph tags saying style attribute equals color red.
So it'll add that inline style right in the website. So this is what's going to
the website. So this is what's going to be happening with the onjoin click function. Now we also need to hook it up
function. Now we also need to hook it up to the button. So the button is going to be the element the user interacts with that we want to run this onjoin click
function when it gets clicked. So to do that we need to do what's called add an event listener.
So because the element that we want the user to interact with by clicking is the button element that button has an ID value of join button. So again we can
use the document getelement by ID join button to target the button. Then we can use the add event listener method and this is going to basically listen or
wait for a certain event to happen on that element. We want it to listen for a
that element. We want it to listen for a click event meaning when a user clicks on the actual element. Then the second parameter is going to be what happens
when that click happens. And we have the name of the function here. So anytime a user clicks on that button, it's going to run the onjoin click function. So
that's basically what happens with our little mini website here. All right. So
let's put into practice these things that we've been learning about using JavaScript to interact with website elements. So in this scenario here, we
elements. So in this scenario here, we are getting flooded with support emails about a bad integration. To deal with this, we have a clickathon challenge page. So when a customer gets to the
page. So when a customer gets to the support page, they have 5 minutes to click a button as many times as possible while the timer is running out. But then
when the timer hits zero, it just resets to another 5 minutes. So we're going to check out the index.html file, which I have opened here. And we're going to look at the website and see where we're
starting from. So
starting from. So here's the website, and it has, you know, some website content, headline, and paragraph. And then we have these
and paragraph. And then we have these buttons as well as time left and then number of clicks. So right now we have a start button that we can click. We have
this other click me button which we cannot click. It's been disabled. And
cannot click. It's been disabled. And
then we're tracking the time left 300 seconds which is 5 minutes and then the number of clicks which starts at zero.
So let's take a look at the code that we have here. So in our HTML we have some
have here. So in our HTML we have some styles just kind of basic styles here.
And then here's the content of the website which we have. So the start button and the click buttons are both these button elements with ids. Start
button and click button. Then we have these paragraph tags which also have ids. And we're going to be updating and
ids. And we're going to be updating and working with each of these four elements in the code. So now here's our starter JavaScript code.
So we have some variables. So we're
tracking the number of clicks and we're also tracking the countdown timer and these are the their initial values. Then
we have a bunch of functions. So the
first function we have is the update UI function that they've already given to us and it basically updates the those two paragraph tags here with the time
left and then the number of clicks.
Then the part that we're going to be coding is these functions here.
So let's take a look at the assignment again. So the first thing is we need to
again. So the first thing is we need to complete the tick function. So with the tick function, we are going to decrement the countdown by one every second. If
the countdown reaches zero, reset it to 300 and then reset clicks and then update the UI by running I'm assuming this update UI function here.
Next thing we want to look at is the on click function. So this will get clicked
click function. So this will get clicked every time the click me button is pressed. So it's going to increment
pressed. So it's going to increment clicks that variable and then update the UI. And the third function is on start.
UI. And the third function is on start.
So when we run on start, it's going to enable the click me button and disable the start button. And then we also want to start a timer using set interval that
will run the tick function every second.
So those are the things that we need to do. And yeah, under the functions we
do. And yeah, under the functions we have our event listeners for the start button. So when the start button is
button. So when the start button is clicked, it's going to run the onst start function. When the click button is
start function. When the click button is clicked, it's going to run the onclick function. And then we have the click
function. And then we have the click button is disabled set to true. All
right, so let's get started here. So
we're going to first look at the tick function. And it says decrement the
function. And it says decrement the countdown variable by one every second.
So countdown decrement by one. So minus minus. It
says one every second here, but it also later on said on the onstart function, we're going to use a set interval that will run tick every second. So I don't think we need
every second. So I don't think we need to do the timing based things in the tick function itself because it's already going to be run every 1 second.
So I think this is good. And then if countdown reaches zero, reset to 300 and reset clicks to zero. And then update the UI. So if
the UI. So if countdown I guess if it equals zero
then set countdown to 300 and reset clicks to zero and then update the UI. So I guess we'll
just update the UI at the very end.
Okay.
And I think I would sort of like to test the click function and make sure it's working. So the tick function should get
working. So the tick function should get run when you click the onstar button here. So let's just do the the start
here. So let's just do the the start button and then the timer stuff first before the the click stuff. Okay. So
when we hit the start button, we want to enable click me and disable the start button. So we can kind of use this code
button. So we can kind of use this code that they have here. So we want to enable click or sorry disabled
set to false. And then we want to disable the start button. Okay. So that
looks pretty good. Then we also want to set interval that calls tick every second. So
second. So set interval calls tick. So tick, comma, and then how often it's going to happen every second, which is 1,000
milliseconds. Okay, so
milliseconds. Okay, so we have our start button, which should be working, and it's wired up because it has the add event listener, and then we
have the tick function, which is decrementing the countdown and updating the UI. So let's see if this works. I'm
the UI. So let's see if this works. I'm
going to reload the website. So we can see here we have time left starts at 300.
So let's click the start button and see if that changes. So what I'm hoping will happen is the 300 will decrease by one every second. Oh, nice. Looks like it's
every second. Oh, nice. Looks like it's working. And then the start button is
working. And then the start button is disabled and click button is enabled.
So I think that part seems pretty good.
So this should be good. Now let's go back up to the on click function. So
when we click the click me button, we want to increment the clicks counter. So
clicks go up by one and update UI.
That looks pretty good. Okay. So let's
reload the website and see if the clicking functionality works. So start
timer is working. Click me. Nice. So
that looks pretty good.
So the clicking function is working. I
think the only thing I want to check is what happens when the countdown hits zero. But I obviously don't want to wait
zero. But I obviously don't want to wait five minutes to do that. So let's kind of modify the countdown. We'll just
start the countdown from five and we'll change this back to 300 later on.
So let's reload.
So start. So now it's going down from five. So it should go to 300 again.
five. So it should go to 300 again.
Okay, nice. So I think that part works.
So, we'll change this back to 300.
And I think that might be everything that we needed to take care of. Let's sort of double check this. Increment clicks. We
did that. Update UI. So, I think that part's done. So, we did all those. Okay.
part's done. So, we did all those. Okay.
So, I think maybe we're done with this. Let's
say I'm done. Oh, let's just check the solution. Here we go. So, here's a tick.
solution. Here we go. So, here's a tick.
If countdown equals zero, countdown is set to 300. Okay, so I think that is the same. We have our on click function to
same. We have our on click function to increment clicks and update UI. We have
the onst start function and set interval is what we had.
And these are they gave that this bottom part to us already. So I think this is pretty set.
All right. Nice. All right. So let's
talk about ECMAScript.
So, ECMAScript is the standard that JavaScript is based on and it's kind of like there's a lot of web standards for HTML, CSS, and JavaScript. And it
basically makes sure everything across different browsers sort of everything works the same. So, the purpose is to help JavaScript and other languages maintain compatibility across different
runtimes. ECMAScript versions are
runtimes. ECMAScript versions are released yearly and they have a big impact on how we write JavaScript. So
here are some of the big changes in versions. So in 2009, ECMAScript 5
versions. So in 2009, ECMAScript 5 introduced strict mode and JSON support.
ECMAS script 6 introduced let and const.
ECMAScript 8 introduced async aait. So
these are really big changes and yes, just to make sure everyone's kind of on the same page in terms of how it's supposed to behave no matter what runtime you're using. So a little quiz question here. Eggmas script is the
question here. Eggmas script is the standard that defines JavaScript. I am
pretty sure yeah that's the answer.
Nice. So when we're talking about JavaScript standards and how they might change and update every year, you will inevitably run into problems where you know you might have a browser that's not
going to support the newest version of the JavaScript standard. So what do you do in that case? Well, that's where we can have polyfills and transpilers.
So what polyfills do from what I understand is it kind of lets you add some extra code so that if a browser does not support sort of the newer syntax of whatever it is, the polyfill
will make it work with the sort of older syntax that the older browser does support. So polyfill is kind of like a
support. So polyfill is kind of like a like a patch job where you're just adding these patches in order to fix wherever the gap might be with older browsers or other runtimes. And then to
compare with that, a transpiler is sort of like a polyfill but kind of like on a much bigger scale where it's going to take your entire code in JavaScript and
it's going to convert it and any newer syntax that might not be supported in older browsers will get basically rewritten into the older syntax. So this
is nice because you can support, you know, older browsers if you need to, but you can still write your actual code using the newer syntax and then you just
use the transpiler like Babel to make it supported by older browsers. So we're
going to try to do that here in this assignment.
All right. So we want to update our heer code. Instead of statically saying moo,
code. Instead of statically saying moo, the code should say moo name where name is dynamically inserted using a template literal. So let's go to our terminal
literal. So let's go to our terminal here and we want to edit the main.js file. So right now it says console log
file. So right now it says console log moo.
So let's rework that with back ticks and we want to say moo comm, name.
Oops. What did I do? moo comma
name exclamation point.
Okay, so I think that looks correct.
Let's save.
And then we want to use Babel to support older browsers that can't use template literal.
So update your code main.js, which we did. install Babel in your project
did. install Babel in your project directory to transpile into modern JavaScript.
So let's do that.
So we'll paste in that command and run it.
Okay, so we have installed Babel core, Babel CLI, and then Babel preset env for whatever JavaScript features need to be transpiled to older syntax depending on
what environment we want to support. And
it's saying if you haven't done so, now would be a great time to create a git ignore file. So I guess we can do that,
ignore file. So I guess we can do that, too. So touch.get getting ignore
too. So touch.get getting ignore nano and then node modules.
And then we want to create a babel rc file.
So babel rc and then edit it and then following content. So, this is basically what we
content. So, this is basically what we want to support when we transpile.
I'm just going to manually type it out.
Presets at Babel SL preset env.
Okay, so that seems correct.
save.
Okay.
So now we're going to actually use Babel which we installed to transpile the main.js file to the older version. So
I'll just copy it from there.
Paste in. So what we're doing is npx babel to run babel and then we're affecting the main.js file. So let's do that. Okay. And now you need to check
that. Okay. And now you need to check that the resulting main compiled JS file. Make sure we have that. We do.
file. Make sure we have that. We do.
Doesn't contain any template literal syntax. So no back tick. So nano main
syntax. So no back tick. So nano main compiled js.
And look, it's using concat instead of actix. So I think we're pretty good
actix. So I think we're pretty good here.
All right. So now run and submit these CLI tests.
So, we'll copy this.
And then let's just clear that. We're
going to run.
Um, I think that looks good. And then let's now submit our code.
Uh-oh. Expected
main compile.js JS to contain none of back ticks. Oh, hold on. I thought we
back ticks. Oh, hold on. I thought we got rid of that.
Yeah, it doesn't have back ticks. H, not
sure what happened here. Oh, name is not defined. I don't know if that is what
defined. I don't know if that is what has caused the error. I'm just going to try maybe
setting name to something just to like Maybe it needs to not be in all caps. So
let name equals coder coder and then name.
So let's save that and then let's run the babel again.
Okay. And now let's edit the main compiled. Okay. So that seems good.
main compiled. Okay. So that seems good.
Let's try again. I'm going to try to run it again.
Okay, so I think that was okay. Now,
let's try submitting it again.
Okay, that works. I think it was just like I didn't have the actual name variable. All righty. I think we're
variable. All righty. I think we're doing pretty good here. And I think we're actually done with um chapter 14.
Yes, we are. All right. So, next up is going to be the last chapter, chapter 15.
Back in the earliest days of JavaScript, when it was but just a browser language, JavaScript files were pretty small. They
were just little scripts, a call back here, a DOM manipulation there. It just
wasn't that much code to worry about.
But as the web has evolved, we've frankly shoved a lot of logic into some websites to the point that we don't even really call them web sites anymore. More
like web apps. Because when you load them, you're literally downloading a full application that's powered by JavaScript. Some of these single page
JavaScript. Some of these single page applications that you develop with a library like React or Vue, they're just a shell of an HTML file and then a
massive bundle of JavaScript that dynamically injects stuff into the page.
So in order to manage all of this code, JavaScript needed a module system. We
needed a way to organize JavaScript code across many different files in the same codebase. So the first system was sort
codebase. So the first system was sort of developed by NodeJS because it was really necessary on the back end. And
it's called CommonJS. And JavaScript
modules like the ones in Common.js exist at the file level similar to Python, not at the directory level, which is how Go does it. So let's take this example of a
does it. So let's take this example of a math.js js file, we define an add function and a subtract function. And
then we export them using the module.exports
module.exports object. Then in another file, main.js,
object. Then in another file, main.js, probably the one we're intending to run directly, we can import them using the built-in require function and then call them and see the results. Now, like I
said, CommonJS was shipped with Node.
And since then, there's actually now become a standard with ECMAScript 6 that we have a new module system, ES6 modules. Instead of modules.exports,
modules. Instead of modules.exports,
ES6 modules just have the export keyword. And instead of the require
keyword. And instead of the require function, ES6 modules just have the import keyword. So our math.js file can
import keyword. So our math.js file can become this. And our main.js file can
become this. And our main.js file can become this. Now ES6 modules are an
become this. Now ES6 modules are an ECMAScript standard. So both the browser
ECMAScript standard. So both the browser and back-end runtimes like Node, Bun, and Dino support them. But Node still uses CommonJS kind of by default. So in
order to use ES6 modules, you have to do one of two things. You can add type module to your package.json or you can use the MJS file extensions for your
module scripts instead of JS. I really
prefer the first option. I don't like changing my file extensions. Now when we run JavaScript code in the browser, we use the script tag. Typically, the
script tag can either have inline JavaScript code in between the tags or it can use the source attribute to go fetch a JavaScript file across the network and run it. And to make sure
that that script is ran as a module, we just add type module as an attribute to the tag. Now, on the backend side of the
the tag. Now, on the backend side of the stack, I'd recommend using ES6 modules basically anytime you can. The only time I'd stick with CommonJS is if I'm working in a legacy codebase, I don't
want to update the whole thing because modules not only are the ECMAScript standard, but they do have some other key advantages. My favorite one is that
key advantages. My favorite one is that modules are in strict mode by default, which strict mode is just a really cool thing that JavaScript has that tightens up the language and allows you to do
less things that could end up shooting you in the foot down the road. Modules
are also encapsulated by default. you
don't get access to the global context from inside of a module which again just makes for writing safer and more easily debugable code. All right, so we're now
debugable code. All right, so we're now in chapter 15 and we're talking about modules in JavaScript. So the reason that we need modules is because you know back in the day there wasn't a ton of
JavaScript heavy code going on. We were
basically doing things kind of like in that previous lesson with you know button clicks and running functions and things like that and it worked fine.
However, now the environment has changed and we have, you know, React, we have Vue, we have Node and web apps have just become very JavaScript heavy, you know, depending on if you're using all those
things and that results in a ton of JavaScript code. So, the best way to
JavaScript code. So, the best way to kind of organize all of that is to break them out into what what's known as modules. So, this helps us keep things
modules. So, this helps us keep things organized and also helps kind of prevent conflict between all of the different pieces of code. So how do modules in JavaScript work? Well, this tells us
JavaScript work? Well, this tells us that the modules in JavaScript exist at the file level like Python. So that
means that a JavaScript module can exist as a file. Like for example, we have this file math.js. It has two functions add and subtract. And then um because it's a module, we want to be able to
export those functions so that other JavaScript files can access these functions in their own code. So we can export them by using module exports and
then the name of the functions. Then
when we want to use those functions in other JavaScript files, for example, here in main.js, we can import them by using the require method, I guess. And
then we're loading the path to the original math.js JavaScript file and then importing the specific functions that we want to use. So now we can use the add and subtract functions in this
other JavaScript file. And this is CommonJS syntax. So it's the kind of
CommonJS syntax. So it's the kind of original way that modules were created from what I understand. So let's look at this assignment and you know work with
modules in our existing code. All right.
So I got our code on the left side here and then I have the assignment on the right. So, we're going to continue
right. So, we're going to continue working with our Heer project and we're going to break it out into modules. So,
in Heer, we have that main.js file, but now we're going to create a new file called moo.js. So,
called moo.js. So,
moo.js.
And here, we want to define and export a function named moo in mu.js using commonjs syntax.
And it should take a name string and return the interpolated moo. So let's
create our function const moo equals name
arrow and then here we want it to return the interpolated moo from the last the last time. So I think it was moo
last time. So I think it was moo and then name exclamation point.
Okay, so there's our function. And then
we want to export it. So let's kind of look back up and check the syntax for that. So it's here, module.exports.
that. So it's here, module.exports.
Module.exports.
And then the name of the function moo.
Okay. So that should be all set for the.js file. So I'll just check these.
the.js file. So I'll just check these.
Then we want to modify main.js to import and use moo. So let's delete this. So we
want to import and use moo. So let's
again go back up here to the example.
So const in curly brackets the name of the function moo equals and we load it with require and then moo.js.
moo.js.
Okay.
Then what do we need to do to import and use moo before logging the output. So
console log moo and then we also want to give it a parameter. I guess I can try to do this
parameter. I guess I can try to do this here. Coder coder and I think my
here. Coder coder and I think my prettier settings change the double quotes to single quotes. So just noting that.
Okay. So now we have main.js and moo.js.
So let's try running our script using node main.js and it is indeed printing what we have
here. Okay, so I think our code is
here. Okay, so I think our code is working. Now we can try running and
working. Now we can try running and submitting our CLI tests. So copy the run and then let's see.
Okay, I think that's a good thing. Yeah,
expect exit code zero.
So that seems good. So now let's try submitting. Nice. All tests passed. Yay.
submitting. Nice. All tests passed. Yay.
So in the last lesson we were using the commonJS type of modules in JavaScript.
This is the older way of doing modules before the new syntax ES6 module syntax was introduced, but it's still used just
not as much as it was before. So one
note here, Common.js CommonJS is NodeJS specific. You can't use it in the
specific. You can't use it in the browser without using some kind of bundler. And then the defining features
bundler. And then the defining features of CommonJS are the module.exports
object which we used in the require function. So this if you see these in
function. So this if you see these in the code, you know that's a commonJS module. And then here are again are the
module. And then here are again are the examples that we are working with the exporting and importing.
All right. So let's check out our quiz.
What's the primary way to export functions in commonJS?
to export is I'm assuming module exports.
Yeah, that seems right. Module exports.
So let's take a look at what strict mode means. So as we've learned, you know,
means. So as we've learned, you know, throughout this whole course, basically JavaScript is very flexible. Lucy goosey
is how they describe it here. And what
that means is that you can do a lot of things that will sort of end up in failing silently. and you might have a
failing silently. and you might have a bug in your code that you won't realize until you know someone actually encounters it on the production site. So
strict mode is a way to kind of enforce some rules before we get to that point so that it will do these things like eliminate some silent errors by actually throwing an error, fixes some mistakes
that make it difficult to optimize your code, prohibit some syntax that might be defined in future versions of ECMAScript and then in the browser this is undefined in the global scope. So it
kind of adds some sort of rules and guard rails to prevent you know future problems. So how do we use strict mode?
We just need to add the use strict at the top of our file or we can add it for just a specific function inside the function there. And one thing to note is
function there. And one thing to note is that the sort of newer version of JavaScript modules ES6 modules are always in strict mode by default. So you
don't have to specify use strict when you're using those. But we have so far been working with CommonJS modules which means we do need to explicitly say use
strict if we want to use strict mode.
Okay, let's work on this assignment here. Okay, so we need to create a new
here. Okay, so we need to create a new file called strict.js and then in the file we want to assign mood to an undeclared variable and then
console log that variable. Okay. And
then let's run the script. So node
strict.js and it is indeed logging our message with our undeclared variable. Okay. So
now let's see what happens when we are using strict mode. So at the top of the file we have to say use strict. Oops
strict. There we go. And now let's try running the script again.
So now we have an error and it says message is not defined. That seems
pretty good. So, let's run our test.
Exit code zero. And things look good.
So, I'm going to submit the test now.
Nice. All right. So, we've been working with the common JS modules which were the original version. Now, let's check out how what we can do with the newer
ES6 modules. So to use the ES6 modules,
ES6 modules. So to use the ES6 modules, we can export from a module using the export keyword like this. So instead of doing module.exports,
doing module.exports, we can just say export, you know, the individual variable or function. And
then to import it in the main.js file, we can say import whatever functions we want from here. So
the syntax is just slightly different from using the require keyword, but it does pretty much the same thing.
So let's look at the quiz here. Which
keyword is used to import functions from an ES6 module?
Import.
Yay. All righty. So with NodeJS, it's going to by default use the common JS syntax in the JavaScript modules, but we can change and use the ES6 uh syntax for
modules uh one of two ways. One is we rename our module files to MJS instead of JS, but changing your file extension seems kind of weird to me and I feel like that would be kind of annoying to
do it for every single file. The other
option is modifying our package JSON file to say type module. So I feel like that makes a lot more sense and it's
more efficient I think. So let's do that with the modules that we have in our Heer project. So update package JSON to
Heer project. So update package JSON to allow for ES6 modules. So let's open our package JSON.
I'm not sure where to put type here, but maybe at the top.
type module.
Let me just make sure I did that right.
Yeah. Type module. Okay. Then update
moo.js.
Replace module exports equals moo with an ES6 export.
I think it was just export moo. I can't
remember. Let's go back and check. Here
we go. Export.
So I did that wrong. So you export it when you declare it. So export const moo etc.
And then we need to import it into our main.js file. So
main.js file. So instead of the require syntax, we're just going to say import moo
from moo.js. And again, just pretend
from moo.js. And again, just pretend these are double quotes. I just had my prettier settings. Um, move everything
prettier settings. Um, move everything to single quotes. But I think both will work. Okay, so I think that's good.
work. Okay, so I think that's good.
Let's go back to the assignment. Data
our main.js. JS. Oh yeah, remove use strict from strict.js.
So with ES6 imports, it should still throw an error. So let's try that node strict.js.
strict.js.
And we have an error. Nice. Okay, so I think we're ready to run our tests.
And we have our messages not defined error which is good. I just want to make sure we do want it to be on the throwing an error. Yeah, with ES6 imports it
an error. Yeah, with ES6 imports it should still throw an error. So I think we want it to have the error when we submit. Yeah. So we're not going to fix
submit. Yeah. So we're not going to fix the error. We'll just submit it as is.
the error. We'll just submit it as is.
Yay. All right. So you know we are talking about ESX modules but how do we actually load them in our browser? So,
you know, you probably know that in your index.html file, you can load a JavaScript file using the script tags here with the source attribute pointing to, you know, wherever the JavaScript
file is. Now, if we want to use ES6
file is. Now, if we want to use ES6 modules and load them using script tags, we have to use the type equals module attribute inside the script tag.
Otherwise, it's not going to load as an ES6 module. And some reasons why we
ES6 module. And some reasons why we might want to use ES6 modules um in our browser things in module are not in the global scope which is good because it will help you know prevent conflicts and
things like that. Also modules are deferred by default. So this is going to mean that your website will load a little faster because it's going to load the main document and then it'll load
all the module files after that. And
then strict mode is enabled by default which is always a good thing. So let's
check out this assignment here. We're
going to do some JavaScript in the browser. So, we want to create a new
browser. So, we want to create a new file called index.html.
So, in VS Code, I created a new folder test um just to make it separate from the heer stuff. So, let's code index html.
Copy and paste the code into the index.html file and then open it in our favorite browser. Okay. And this is kind of it.
browser. Okay. And this is kind of it.
And it does look a little plain and also bright if you're used to dark mode. So
what went wrong here? If we open our browser's developer console, we should see some errors. So let's do that. Okay.
So here's the errors. Document body is null. Import declarations may only
null. Import declarations may only appear at the top level of a module. And
then I don't know what this one is. It
might be kind of unrelated. Okay. So we
have a syntax error. This is caused by the import in the second script tag. So
let's look at that.
So, I'm just looking at the source code here in the browser. The script tag.
Here's one.
Oh, yeah. So, this one says import confetti. And then there is a type error
confetti. And then there is a type error here. This happens because the script
here. This happens because the script executes before the page content exists.
That makes sense. So, we want to fix the script tag. So, the code executes after
script tag. So, the code executes after the page load and the import statement works. I'm assuming we want to do this
works. I'm assuming we want to do this by loading them as modules. Oh, wait.
This is the CSS. Let's fold that up.
Okay. Here, script type equals module.
I think that's right.
And then the next one, same thing.
So, let's see if that works.
So, this should fix the code executing before the page loads because it'll now defer it because it's a module. So it'll get loaded after the
a module. So it'll get loaded after the actual page loads and it should make the import statement work as well. So let's
try reloading. And it looks different.
Let's check out our console again. So
the errors are gone. This one I think is not related to the boot.dev stuff. So I
think we have fixed everything which is pretty great. There we go.
Nice. Okay. So we did that and we are profiting. Done.
profiting. Done.
Cool. All right. So what are default exports? These are used when we want to
exports? These are used when we want to export just a single value from a module. So let's look at what we had
module. So let's look at what we had done earlier with math.js. We had the add and subtract functions and we exported both of them. And then in our
main.js file, we would import them using curly brackets and then the two function names. However, if we only wanted to
names. However, if we only wanted to export the add function and not the subtract function in our math.js file,
we could say export default const add instead of export const add. And adding
that extra default word means that this is the only thing getting exported. Then
when we import it, we can just write import add from math.js without needing to have these curly brackets which we had before. So, it seems like it's could
had before. So, it seems like it's could be more convenient, but I feel like yeah, if you end up wanting to import um sub subtract later on, then you would have to go back and change remove the
default, add the curly brackets in. So,
it just seems kind of safer to use curly brackets no matter what, but I guess this exists just in case you wanted to do this. All right, so let's look at the quiz. Default exports
are different from named exports because they don't need curly braces when imported is my guess. Yeah.
Yeah. They don't need curly braces seems to be the main difference. Nice. All
right. So, let's talk about bundlers and why we need to use them. So, if we are working with something like React and we have a really large codebase, we're going to have a whole lot of JavaScript
and other files in our codebase. And
this is optimized for the developer experience where you know we want things split up in separate files and organized so we can find what we need and you know makes it easier to fix bugs and things
like that. However, that's not the best
like that. However, that's not the best format for you know the visitors to your website. For the browser it's more ideal
website. For the browser it's more ideal to have a fewer number of files and have files be smaller and more optimized and things like that. So that's kind of what the bundler does. So the bundler takes you know the giant codebase that you
have optimized for the developer use and then it bundles things and optimizes things so that the files um at the end are best for loading in the browser. So
here are some things that bundlers can do. So bundling so multiple files into
do. So bundling so multiple files into one or smaller number of files can also minify your files. So it'll remove white space from your JavaScript and CSS files to make the files themselves just
smaller. It can split your code into
smaller. It can split your code into smaller chunks. It can remove unused
smaller chunks. It can remove unused code from the final bundle, which is nice. And then it does some things like
nice. And then it does some things like optimizing your images, which is a really big space saver for websites. And
then also can create source maps. So
even if you get everything bundled, it'll tell you where the original file was, so you can locate it for easier bug fixing. So bundlers do a lot, and for a
fixing. So bundlers do a lot, and for a long time, Webpack was the most popular bundler. I don't know if it was the
bundler. I don't know if it was the first one, but it seemed to be the first one that people were really talking about for Angular and React and stuff like that. However, nowadays it seems
like that. However, nowadays it seems like more people are going towards Vit.
And I've used Vit a few times and I have to say it's like super easy to set up.
It doesn't need a lot of configuration out of the box like Webpack does. So,
it's just a lot more beginner friendly.
So, we're going to try to use a bundler in our Heer project here. So, let's
scoot this over. And here's our assignment here. All right. So, we have
assignment here. All right. So, we have our Heer codebase. We now are going to try to use a bundler. So we're going to install cows which is a npm package for
our moo program and then use vit to bundle it. So we want to install cows.
bundle it. So we want to install cows.
Okay.
And then we want to import say from cows in main.js. And I haven't really used
in main.js. And I haven't really used cows. I've seen it used. But let's just
cows. I've seen it used. But let's just make sure we're using the right syntax.
I think we wanted to import say. So here
we go. So something like this. Import
say from cows. So let's go to main.js.
So now we want to import Wait, where is the moo thing? I may have overridden this by accident. So import moo
from moo.js. Okay.
from moo.js. Okay.
So now let's import say from cow say. I think that should work. And
cow say. I think that should work. And
then we want to combine the move function with say. So
if we go down here, this is kind of what we want to write. So console log say in parenthesis
and then text property and then let's just move that into the text as a
text value.
Okay, not super confident in this, but I think that's what we want. Let's test
this by just running node main.js.
main.js.
Oh, it worked. Okay, cool. So, that was relatively easy, I think. All right, so now we're going to install Vit and bundle our files.
So, npm install vit as a dependency. All
right. And then we want to configure V to bundle our CLI by setting a V config.js file at the root of our project. So,
project. So, v.config.js.
v.config.js.
And then we're going to copy this Okay. So, what's happening here? Sorry,
Okay. So, what's happening here? Sorry,
I shouldn't have closed that. So, what's
happening here? The build lib tells me we're generating a library bundle. So, I
guess that's what that is. So, the
build's not based on an HTML file or browser runtime environment. And there's
a single JavaScript entry which is main.js. And this will be packaged. And
main.js. And this will be packaged. And
then the output can be executed in node.
All right. And then formats ES. it'll
get outputed in ES module format. Okay.
So now in our package JSON file we want to add a build script.
So let's copy that. So I'm assuming after dependencies. I think I did
after dependencies. I think I did something wrong. Oh sorry.
something wrong. Oh sorry.
Yeah we don't want that. So it's in the scripts thing here. So just going to copy this and we'll replace what we had here with our V build scripts.
Okay, so now we're going to run the build script with npm run build and this will run this v build. So let's try that.
npm run build.
Okay. And then it should create a disc folder containing the bundled file. So
let's go to our disc folder and let's see what we got in there.
heer.js. So, let's open this just to take a look.
Okay. And yes, it looks like an Eldrich horror, but this is just all the optimized code that we're using, I guess. And then
here's a note. We should add the disc folder to our git ignore file as well, because any files that like get generated during like when you're building is something that you don't want to include in your git because
it'll just be generated whenever the script is run. So, let's open that.
Oh, did I not have this? Oh, sorry. I'm
in the wrong directory. Don't save
ignore.
All right. So, we also want to ignore the disc folder. Okay. So, now
let's run npm run start.
And it looks like everything's running.
Sweet.
Okay, so I think we got everything. So
now let's do our run run our tests.
Okay, that seems good.
And let's submit our code.
Woohoo. Hey, so we've now completed the learn JavaScript course. Yay. And wow,
only 1.4 47% of students have completed this course. All right, great job
this course. All right, great job everybody. So yeah, hope you enjoyed
everybody. So yeah, hope you enjoyed this and this is a very fun experience for me. So yeah, this is
for me. So yeah, this is
Loading video analysis...