Transcripts
1. JavaScript Critical Concepts Introduction: Welcome to this section on critical concepts in JavaScript. In this section, we're going to deal with
what I think are critical concepts
about the language and how JavaScript works. Now some of you may want to
jump ahead two sections that focus more on the language
aspect of JavaScript. But I would urge patients, these concepts are critical. Now, as you start
in this section, some of the concepts may
seem basic because they are. But even if you've been working with
JavaScript for awhile, I'm sure you will
learn something. So stick with it. Now, why are these
concepts critical? Why is it important to understand
how the language works? Because a critical part of any good developer's
understanding is knowing why you
do certain things. The y makes it
possible to adjust patterns or code to fit
your specific needs. The y facilitate
critical thinking. And these concepts provide
the why for many things we do in JavaScript that we
will talk about later on. In fact, as a part
of later sections, you may want to come back and revisit some of these topics, such as the event loop when dealing with asynchronous code. So it's important to spend some time talking about
the JavaScript engine, the call stack, the memory heap. The fact that JavaScript
is single threaded, the runtime environment
and the event loop. So let's jump into it.
2. The JavaScript Runtime Environment: In order for us to make
use of JavaScript, we need an environment
where it will run. Now, JavaScript
doesn't require a lot of tools in order to write code. In fact, we can just open a simple text editor and
begin writing JavaScript. But in order for
that code to make sense or to do anything, we need to make the
code available to a JavaScript runtime
environment. Now there are two main
runtime environments that make up the majority of
the use of JavaScript, the browser, and NodeJS. So we can have JavaScript
run and complete some task using either
the browser or node. Now, these two are not the only environments
we could use, but they are the most important
and the most prevalent. Now there are some similarities between node and browsers, and then there are
some differences. Let's talk about those briefly. First, both a browser and node
is simply an application. In each case, they need to be installed on your
computer to use them. We installed Node
earlier in the course. When I start up a browser, in this case Chrome, I'm starting up that
application from my computer. Now the same is true with node. We simply use it differently. We need to use it from the
terminal or command prompt. And we don't usually
use a GUI interface. For example, I can access
node by typing that in. And now I have a node prompt. That's how I use node. Another similarity is
that these applications, meaning both the
browser and node, are written with the
same computer language. Now in the case of Chrome and most browsers for that fact, the core of that application
is written in C plus plus. The GUI is usually a
different language, but the core is C plus plus. Now, the core of NodeJS is also written in
C plus plus with some JavaScript
code that acts as a wrapper for some of
the commands we use. The code. Those two
applications are written in the browser and node
is very similar, but that is not what makes
it possible for us to use JavaScript in each
of those environments. In order for a JavaScript
runtime environment to allow the use of JavaScript, it needs something to
interpret the language, to read the JavaScript and
translate it for the computer. That very important piece is called the JavaScript engine. Both a browser and node require a JavaScript engine
in order to use JavaScript. Now the JavaScript engine is just a piece of the
entire application. There are a lot of
other pieces to a browser and there are lots
of other pieces to node. Let's take a look
at a diagram that illustrates the runtime
environment for our browser. These are all the
pieces we are going to be talking about because we interact with them when we use
JavaScript in the browser. So if this whole thing represents the browser
and what it contains, we can see that there
are things that are not apart of the JavaScript engine, which is represented up here. We sometimes do
things in JavaScript that make use of parts of the browser application
that is not a part of the JavaScript engine. Now these other parts or pieces are some of the things that are
different between a browser and known. For example, in a browser, we interact with the DOM, extensively represented
here in the web APIs. Well, that is not
something we do in Node. There is no DOM that
is a part of node. However known makes it possible to do other types of tasks. Tasks that are
required on a server, such as write a file to a
hard drive or start a server. Those are things that we
can't do in a browser. So there are some differences. Let's take a look at another
difference really quick. So here in a browser, if I open up the console, I can display window. That displays the window object. This is the global environment that we're writing code in. When we're writing JavaScript
is inside of the window. And there's a lot of
associated with the window, which we can make use of. Now node doesn't have a window. If we type window here, uncaught reference, our
window is not defined. However, we can type global. And we do get information
about global. And this would be the equivalent to Window on the browser side. Now, of course, there are
going to be similarities. For example, you can see
setTimeout here within global. Settimeout is available
in the browser as well. You can see it's not in
the JavaScript engine. It's actually part
of the web API. Same thing with node. It's not a part of the
JavaScript engine, but we have access to it. And we can do something
like console.log here. And just like we can
do in a browser. Now, over the next
several topics, we're going to be talking
about these different parts of a browser as they are
critical to understand. In order to effectively
write, JavaScript. Node also has additional parts, but we will focus
mostly on the browser. First off, we're going to talk about the
JavaScript engine.
3. Understanding the JavaScript Engine: Simply stated, the
JavaScript engine is a program that executes
JavaScript code. So looking at our diagram, if we have some JavaScript code, the JavaScript
engine is in charge. It is the only piece that knows
what to do with the code. It translates it into something that the
computer can understand. Now, initial JavaScript engines early on were interpreters, which means they would process the JavaScript
code line by line, convert it to bytecode
so it could run. Interpreters are quit to
start running the code, which is something
that was needed in the browser environment. But they can be
slower overall when compared to compile the code. Compiled code is
converting the program to machine code so that
it runs optimized. The latest JavaScript engines
are much more optimized. They use a combination of an interpreter and just in time, compilation or JIT compiler
to optimize the code. This gets the best
of both worlds. Jit compilation takes cold that can be optimized
and compiles it. For example, if a piece
of code runs a lot, it can be compiled
to machine code. And then when that
piece of code does run, it is optimized and
therefore faster. Now, there are a number
of JavaScript engines. The one that is
probably the most well-known is the V8 engine. This is the engine
that is used in the Chrome browser
and also in node. This engine was written by Google for Chrome
using C plus plus. And it is open source. It is probably the
most well-known engine because when it was built, it improved the speed of
existing JavaScript engines. Google was using
JavaScript to do some pretty amazing
things at that time. Think about the
different Google apps written with JavaScript. Anyway, they wanted it
to be more performant. So they wrote the V8 engine
to accomplish exactly that. Other JavaScript engines
followed suit in order to make their engines more
for performance as well. This improvement in
performance is important to be aware of this idea of using a JIT compiler with an interpreter to
help optimize the code. The reason this is
important because we talk about writing code
certain ways to make it more performance or avoid things in our code that could make it
less performance. Many times it has to do with the way the JavaScript engine handles the code and is
able to optimize it. Now, here are some other
JavaScript engines you may have encountered. We've already mentioned V8
that it was open source, that was developed by Google. It's used in Chrome and NodeJS. Spider monkey. This was the first
JavaScript engine, and today it's used in Firefox. And incidentally, the first JavaScript engine was written by Brendan Eich when he
invented JavaScript, and as the story goes, did it in ten days. Now, JavaScript
core, that's also open source and that was
developed by Apple for Safari. So that's the engine
that Safari uses. Another one we should
probably mention is chakra. And this is used
in Microsoft Edge. So Microsoft's
JavaScript engine. Now, with all these different JavaScript engines in
different browsers, how do we know that
the JavaScript code we write will work the same
way in each browser. Early in JavaScript's history, this was a real problem. There were differences. In those days. We spent a lot of time worrying about
differences in browsers. Libraries like
jQuery helps solve that issue and became very
popular because of that. Now, because of
these differences, there needed to be
a standard and that is where Acme script comes in. This is a standard that
JavaScript follows. An AGMA script is a specification that all
JavaScript engines now follow. This allows multiple
independent implementations, but it ensures that our
code works the same. So when changes are made
in the script standard, the Indians must be updated
to support these changes. Some updates are
faster than others. And that is why we have
sites like this one. Can I use.com that tell us which browsers support
certain implementations? So we can see the history of different browsers
and when they started supporting ES modules
in this example. Now, that is also why we
make use of transpiler. A transpiler like babble, let you write code using the lightest Ekman
scripts standard, but then outputs JavaScript
code to an older standard. So an earlier form
of JavaScript that older browser engines can run. This can also be called
a compiler because technically you are compiling code to another form and
older version of JavaScript. Alright, so that is enough
about JavaScript engines. Now we need to get more
into the details and talk about the heap and the call
stack within the engines. These two things are used frequently when
coding in JavaScript, even though you may not
have known about it.
4. The Memory Heap and Call Stack: We're now going to dive
into two features of the JavaScript engine that
are important to understand, memory heap and the call stack. These are used throughout
code execution. First I'll describe each one of them and then
we'll see them in action to better understand how they are involved
in code execution. Now, the memory heap, as the name indicates, has to do with
memory allocation. Whenever you define a
variable object function, anything like that in your code, there needs to be a
place to store it. So like these variables here would be stored in
the memory heap. Whenever a declaration is
encountered, such as this, the value is placed
in the memory heap, and then the location of that value is placed
in the variable. Then whenever the code needs that value or the function
or whatever is stored, it uses the memory
location to look it up. Now the memory has a
limited amount of memory, so complex programs that
have a lot of variables and nested objects can
chew up that memory. The JavaScript engine tries to make more memory
available by clearing out data from the
program that it determines is no
longer necessary. This process is called
garbage collection. There are things you
can do as a programmer to assist in garbage collection. And there are things you could
do that could hinder it. We will look at
this in more detail in the topic on
garbage collection. But for now, let's talk
about the call stack. Anytime we run code, the call stack is used. It is simply a place in memory that keeps
track of the function executing and the functions that are going to be
executed after that. So the order in which these
commands are executed. Now, each function is placed on top of the
previous function. So the first function in is at the bottom
of the call stack. And then as other
functions are called, they're placed on top of it. So the call stack follows a
first in, last out approach. Now as soon as the function or command is completed is
removed from the call stack. Now, as you can see
from the diagram, there is only a single
call stack depicted. The JavaScript engine only has one call stack to deal with
commands that are executing. That is because JavaScript
is single threaded, a term you may have heard of. Now, a single thread means
that the JavaScript engine can only execute one part of
the program at a time. So the call stack deals
with one command at a time. And as a result of this,
JavaScript is synchronous. Commands can only be
executed one at a time. You can probably see a
possible problem with this. What if we invoke
a function that requires a long time to run? How can we prevent that
from blocking other code? For example, we want a
user to be able to click on a button and not have to wait two seconds
for some JavaScript to finish before it can
respond to that button. Now, we'll dive into
how this is handled and how the JavaScript engine deals with it when we talk
about the event loop. And this is also why
it's important to understand asynchronous JavaScript patterns
in JavaScript. And that's one of
the critical parts that we deal with
in this course. Now, in our diagram,
as you can see, we have some very simple code. Let's walk through it with the memory heap
and the call stack illustrate how those are used
in moving through the code. Basically what we're
doing is we're declaring two
variables, a and B. Then we have a
function declared. And then we invoke
that function here. Inside of the function, we call console log. We call setTimeout and pass
in a function to setTimeout. The time for that
is 0 milliseconds. And then we call
console log again. So let's move through this. First we have the
variable declarations. And so each one of
those are going to be placed in the memory heap. There's 1 second. Now there is no
specific order in how they are placed in the heap. They just need a reference to where that value is located. Then we have our function. And that's going to need to be placed in the heap as well. And there we've added
that to the memory heap. Now if there were any variables declared inside
of that function, those would need to
be placed in there. Or if there are functions
declared inside it, if there are other things inside that need to
go into memory heap, that would need to happen. But now we encounter. The call to helloworld to that function.
We're invoking it. So the JavaScript engine grabs that code from its
memory location, and then it's able
to begin executing it using the call stack. So the hello-world
function is placed on the call stack that
indicates where we are at within
the code execution. So right now we are inside
of function helloworld. We come to the first
command in there, and that is a call
to console.log. So we our invoking
console dot log and that gets placed
on the call stack. Now we're able to
complete that command. And so once that
command is complete, it is removed from
the call stack and we're able to continue on. And we get to set timeout and setTimeout is added
to the call stack. However, setTimeout
is something that is a part of the web API, as you can see over here. So JavaScript doesn't need
to do anything with that. So basically it gets rid of it. It sends it to the
browser and says, Here, I've got to
call the setTimeout. Here's the information. You go ahead and
take care of it. And then to JavaScript
engine forgets about it at that point, the web API, we'll set up a timer for
that setTimeout and it will handle everything that needs to be handled with setTimeout. But at this point,
the JavaScript engine as simply forgotten about it. It's not worried
about it anymore. It simply continues on
to the next command, which is another
colleague, console.log. And so that gets added
to our call stack. We're able to take care
of that right away. We send a message
to the console, which happens to be world. And then that's removed
from the call stack. And then at that point we're at the end of the
hello-world function. And so that is removed
from the call stack. Now, you can see how the call stack could get built up with a
number of things. If we had functions called
inside of other functions. And the more we have nested
functions like that, the more things
that are going to be added to the call stack. And we'll build up
on that call stack. Because until a
function returns, until it completes, it cannot be removed
from the call stack. Now with this whole
illustration, I left setTimeout over there and said the JavaScript
engine just forgot about it. Well, we're going to talk about that when we get to the
topic on the event loop, because really it is
the event loop and the message queue
that deal with that, that deal with these
web API items. So we'll discuss that
in another topic. But before we move
to the next topic, I want to address
something we can encounter with the call stack
is called Stack Overflow. And this is a
condition you may have run into with your coding. This occurs when the
call stack fills up because it can't remove commands and more keep
getting added to it. I mentioned that
nested functions could add a lot to
the call stack. Well, it takes quite
a bit in order for the call stack to fill up. But when it does fill up, it causes an error. Now, we can simulate this pretty easily with a recursive call. Now, recursion is simply when
a function calls itself. And there are some
situations where this is an advantageous
pattern in JavaScript. But I want to show
you the effects of what it does on the stack. So let's go ahead and set up a function that will
illustrate this. This JavaScript file is
attached to the HTML file. This one here that we're
looking at previously. I'm just gonna put a function on it and call it self ramus. See what happens. So let me call it recursion. There's not necessary
to call it that, but I'm gonna do that because
I'm gonna be calling it. And then I'm going to set
the number that is passed in equal to itself plus itself, something simple like that. And then here is where
the recursion happens. We invoke itself from inside. So think about what this is
going to do. The call stack. We're going to call recursion is going to place
recursion on the call stack is going to get
down to this line. And recursion is going
to be called again, but the function
hasn't completed, so it's not removed
from the call stack. Another invocation of that
is added to the call stack. And so it keeps
adding recursion to the call stack until
it builds up to the point that it
can't add anymore. And that's where we get
that stack overflow. Let me go ahead and invoke this. Going to pass in the number one. We'll save that. Now since I just have that
attached to this HTML file, I'm just going to refresh
that and see what happens. Let's open up the console
and see what we have there. We have an air uncaught range. Our maximum call
stack size exceeded. This is the air
we would receive. If we had a stack overflow. Maximum call stack
size exceeded, and that's what
we're getting there. Now this is a simple
problem to solve. All we have to do
is make sure that eventually the functions start completing, that they return. And then it can remove
them from the call stack. Eventually remove all of them
from the skull call stack. Let's look at how
that might be done. Let's say that if the number is greater than and I'm just going to
put a large number here. I'm no idea how big
it's going to be, but if it's greater than that, then I'm just going to
log to the console. I want to see how
big the number is, just for the fun of it. And then I'm going to return. So here's where we're
returning from this function. So it will complete the
function, we return here. It won't do this again. And it will complete that
function that we're in. And so then it will
unwind the call stack, each of those functions. We'll finally get to return because it'll get to
the end of the function. And so the fact that the last time we call
this, where the, where num is greater than this, that forces a return, doesn't call another one. And so all of those others
that are in the call stack get to complete as well. And so then we don't get
that stack overflow. Alright, let's look at
that just one more time. I'm going to refresh here. I want to remember is
not getting larger if I don't pass it back in when
I call that function. So I want to make sure
it's getting larger. There we go. Now we get a very large number coming out and we're
no longer getting the stack overflow because
was able to return. And then unwind all of those function calls
that are in the stack. So that's what we're
referring to when we're talking about
StackOverflow. Alright, let's move
on to the next topic.
5. Understanding Garbage Collection: In the previous topic, we mentioned garbage collection in connection with
the memory heap. In a language like C, we have to allocate
and release memory. Let's not so in JavaScript, but there still needs to be a mechanism for
reclaiming memory. So we don't run out of
memory and crash the system. Javascript handles the
reclaiming of memory for us. Once a piece of information, an object or variable, is out of context and
won't be used anymore. It's memory is reclaimed, so it can be re-used. This is called
garbage collection. Let's take a look at how
that works in the engine. Garbage collection takes
place in the memory heap and it uses what is sometimes called a mark and
sweep algorithm. It determines the
objects that can be safely deleted from
the memory heat by determining which things are reachable and which
are unreachable. And then it sweeps through
those that are unreachable. They're swept off and
that memory is reclaimed. Let's take a look
at how it works. Now, the garbage collector
starts with the root or global object and moves to the objects referenced by them. And it moves from one
object to another, identifying things that are
referenced by something else. So basically, those things
which are reachable, those things which are not
reachable are now defined. And then everything
that is unreachable, we now see a few things which are not linked or not reachable. Everything that is
unreachable is cleared. It goes through and
sweeps those off. They're gone. That memory can now be reclaimed and use
for something else. Now, as you noticed
in our explanation, order for information
to be freed up and reclaimed must not be connected to anything
currently going on in the program unreachable. While it is possible for our coding to keep things
from being reclaimed, even though we're no
longer using them. This is called a memory leak. Memory leaks are parts of
memory that the application needed and used in the past
and is not needed anymore, but it's storage is yet not
returned to the memory pool. Even though garbage
collection is handled for us. As we've seen, we still need to be cautious
of memory management. Memory leaks can cause
JavaScript programs to fail by using up all of
the available memory. Let's look at some common things that can cause memory leaks. So first off, global variables. If you keep creating
global variables, they will stick
around throughout the execution of the program, even if they're not needed. If these variables are
deeply nested objects, a lot of memory can be wasted. Not removing event listeners
that are no longer needed. As one example of how this
particular thing can happen. You could create a lot
of event listeners for a particular
page or location. And then when the
user moves past that, where those event listeners
are long, no longer needed. You as a programmer,
don't remove them. They're still there. They're still taking up memory, especially for the objects
that are linked to. So something to be aware of. The third item, unclear
time intervals. Now, set interval is a
good example of this. And if you haven't
used set interval, basically what it
does is it allows you to execute some code over and over again based
upon a set amount of time. Now, let's look at a really
quick example of this one. I'm just going to
call set interval. And set interval takes as the
first parameter a function. This is a callback function. So every time the
interval expires, the amount of time we enter it invokes this
callback function. So I'm going to set
up a function here. And then the second
parameter is the amount of time in milliseconds that
each interval happens. So every 200 milliseconds, this function is going
to be invoked, Okay? Now, where this can
become a problem, say inside of here, we reference the
number of objects. Those objects are, are
being referenced there. Sometimes it's kind
of thing is done with animation or
something like that. But if this is never cleared, if this set interval
is not cleared, obviously these references
are still going to be valid. And so it will never
be able to free up that memory even if it's
no longer being used. So a better approach to the
set interval problem is declaring an ID and we set that equal to setInterval that will place an ID inside of here. Then when we are done, we should make sure that we're clear interval with that
ID, something like that. Okay, one more thing
we need to mention, and that's removed DOM elements. If in your program you remove
elements from the DOM. But these elements
are still reference, such as with an event listener. We talked about that earlier, or in some other way, the
memory will not be freed up. Something else to be aware of. Now, we will revisit some of these and other
places in the course so that you have a reminder of best practices to
prevent memory leaks. All of these things we've
talked about can add up and the memory leaks will continue to take more
and more memory. If your program
runs long enough, it could eventually fail
for lack of memory. Even if it doesn't fell, you should make sure to avoid
memory leaks and not just rely on garbage collection
to save the day. Alright, let's move
on to the next topic.
6. Removing Event Listeners to Help with Garbage Collection: In this second topic
on garbage collection, I want to expand on some of
the techniques which are specific to browsers mentioned
in the previous topic. Specifically, I'm
going to address how to remove event
listeners and JavaScript. Not all JavaScript developers are familiar with this feature, but it is critical when talking
about garbage collection. So I wanted to insert it here. Now, if you are coding
for the browser, then you'll be working
with the dawn. The DOM is short for
Document Object Model. It is simply an
interface that allows JavaScript to
manipulate the content, structure and style
of the HTML document. The HTML document is represented using nodes and objects so that the programmer can interface and work with every element
on the HTML page. There are numerous commands
for working with the DOM. I cover these in detail in my Getting Started
course and I've included some of these
topics in the appendix. If you need to review. I've included information
on the DOM and commands for selecting and working
with DOM elements. Alright, now back to
the topic at hand. If you have attached an event listener to an
object or a DOM element, and that event will
no longer be used. It is a good practice
to remove the listener. So let's take a look at example. Let's take a look at the
HTML code for this page, which I'm currently showing. Here it is, as you can see, it's a pretty simple HTML page. We have a title in the heading, we have some CSS. Then in the body here
we have a few div tags. And what I want to do
is I want to attach an event listener
to this div tag here that has an ID of title. So if we take a look at
our JavaScript code, as you can see, this app.js is attached to this HTML file. We have declared a
few variables here. Now, I'm just doing this simplistically to
show an example here. So I have used some
global variables because it's so simple. I don't, I'm not taking the time to do it
a different way. I just want to
show this example. So we have some global
variables here. One is account and one
is a title variable that stores that div that
has an ID of title. That's how I select it there. So we're going to add an
event listener to that. So I come down here and I simply do take that variable
there, add event listener. And we need to indicate
which event it is. It's a click event as
one we want to use. And now what function is
going to call That's title? Click this function here. Now at times you may add event listeners with
anonymous functions, where you declare the
function right here, instead of declaring it
before you declare it inside of the add event
listener. And that's fine. But you need to be aware
that if you do that, you're not able to remove the event listener is a case where you may
need to remove it, then you should do it this way. Alright. I'll talk about the
reason for that in just a minute when we
get to that point. But first, let's just make sure this is working.
I'm going to save that. I already have the virtual
server running on that page. So I'm just going
to resize this. And let's show the
console so we can see the console log message
when I click on the title. And as we can see that
showing up and the counter is incrementing and telling so
many times it's been clicked. Alright, so pretty simple. We've added the
EventListener there. Now let's look at how we would remove that
event listener. So let's say up here, we wanted to remove it once the count was
greater than five. So we're just gonna do
it quick. If statement. If the count is
greater than five. Well that's a situation
where we're going to remove the event listener.
And here's the command. We have to use the same object that the event
listener is attached to. In this case, it's
a DOM element. So tidal dot and
then the command is remove event,
listener, like that. Now this part inside the
parentheses here has to match what we had down here when we set
up the EventListener. And that's why I say that when you'd use
anonymous function, you can't get that to work. You need to declare the
function beforehand. So these things are the same. And even if you declare
options or use capture, anything else, when you set
up the addEventListener, you need to include them up here as well in order to remove them. That's one of the requirements of this remove event
listener command. Alright, so let's go
ahead and save that. That'll refresh the page. You can see those
messages disappeared. Now if we start clicking it, counts, counts, we'll get six. Now it should be removed. Now I'm clicking on it
and nothing is happening. That event listener was removed. So that's basically the process of removing an event listener. Wanted to cover it
here because we were talking about
garbage collection. Alright, let's move on.
7. Understanding the Event Loop: Now before we finish up talking about the
JavaScript engine, we need to talk about
the event loop. Up to this point, we have established that
JavaScript is single threaded. It only has one call stack. It can only do one
thing at a time, so it is synchronous. However, JavaScript allows us
to do asynchronous coding. A simple example of that is adding a button to an HTML page. We can be running
some JavaScript. The user will click the button and we can respond
to that click. Because we have JavaScript
running doing something else. It doesn't block the user
from clicking that button. That would of course, be a horrible experience
on a browser. Another example is
if we are trying to fetch some data
from a database, we make that call to the database and then
we can do something else while we're waiting
for the data to return. We don't have to
sit and wait for that data before we
do something else. And that would block other
JavaScript processing. We can do something else. And then when the data returns, we can act on that data. We can achieve this
asynchronous coding in JavaScript because
of the event loop. In the previous scenario, the setTimeout command was
handled by the Web API. And I mentioned At that point, the JavaScript engine
forgets all about it. Well, once that
timing event is done, once the web API finishes
at timing event, how does that get
integrated back into the call stack so that the task we want
completed gets done. For example, if you remember, we have a callback function
as a part of the setTimeout. How does that call
back function gives back to the JavaScript engine. Let's walk through that
previous scenario again, but this time we will include
the event loop. Once again. Here's our code,
here's our setTimeout. And notice we have
a function here. All the function has within it as a console log
statement, that's all. The milliseconds are set to 0, so the timer should
expire immediately. But let's see what happens. We've gotten to the point where the hello-world
function is invoked. So let's continue to
walk through that. So we have the invocation of the hello-world function that
is added to the call stack. And then it begins
working through the commands inside
that function. And so the first
command we encounter is a console log statement
and it's going to log variable a to the console. And so that's added
to the call stack. It takes care of
that log statement. We see hello on the console. And then the console log command is removed from the call stack. And then we move along
in that function, we encounter the setTimeout. Now, the JavaScript engine knows that setTimeout is
handled by the web API, so it is sent over
there to be dealt with. So the web API sets up a timer. It has the ability
to run a timer. And that timer
expires immediately because we haven't set
to 0 milliseconds. And so when the timer expires, what does it do with
that callback function? That's the thing that
timer is supposed to do. And so what it does is it adds the callback function
to the message queue. Now that callback
function will sit in the message queue and it's at this point the event
loop comes into play. The event loop will
continue to cycle. It will be checking the call
stack and see if it's empty. Right now. It's still working on the
hello-world function. So it is not empty, but at cycles and
continues to look scene. If it's empty. If it's empty, it would then add the next item available in the message queue
into the call stack. But right now it's not empty, so we need to continue with
the hello-world function. What's the next
thing that comes up? Well, it's another
console log statements, so that gets added
to the call stack. And we go ahead and complete that console log statement World is printed to the console. And so that console
log statement is removed from the call stack. At this point we
are finished with the hello-world function that is removed from the
call stack as well. So as I mentioned,
the event loop is cycling and checking
the call stack. So at checks and
sees it, it's empty. It then grabs the next item in the message queue and adds
it to the call stack. And so we get that
anonymous function, that callback function, out
of the call stack and it begins to work through what
that function needs to do. The only thing in it is
a console log statement. It encounters that
console log statement and adds that to the call stack. The console log
statement is completed. An exclamation
point is printed to the console that's removed
from the call stack. That is the end
of that function, and that function is removed
from the call stack as well. And so at this point in
the call stack is empty, there's nothing left to add
from the message queue. And so we're simply
waiting for a number, another JavaScript command
that needs to be executed. Alright, now before we're done, let me just highlight some important points
from this discussion. First, other parts of the JavaScript environment
can handle certain tasks. For example, those tasks
that belong to the browser. The JavaScript engine doesn't
have to process those. We, in this example use the web API to handle
that setTimeout command. But the callbacks that are
a part of what is handled there are integrated back into the engine using
the event loop. It pulls them from
the message queue and adds them to the call stack. We achieve Asynchronous
JavaScript this way. The event loop is critical
in making that happen. Another important point, once a callback is added
to the call stack, the code is handled
by the call stack as it normally would be if the JavaScript code had not come from the Q, doesn't matter. It's going to process that
JavaScript in the same way. Next, a reminder,
the event loop is constantly checking for
items in the queue. And if the call stack is empty, if the call stack is empty and there is something
in the queue, it will add the
next available item from the queue into
the call stack. And as mentioned, the
call stack is one thread, so it is synchronous. It can only do one
thing at a time, but its interaction
with the event loop and the web API allows the asynchronous coding that we can achieve in JavaScript. Alright, let's move
on to the next topic.
8. The Node Runtime Environment: Since NodeJS is such a widely used
implementation of JavaScript, I think it is
important to briefly look at its runtime environment, especially in relation
to the event loop and message queue that we
just talked about. This article here cover some of the ins and outs of the
Node.JS environment. And here is the URL
to this article. You can read it
yourself if you'd like. But I wanted to take
a moment and look at the diagram it provides of
the runtime environment. So if we scroll down here a bit, right here, the node JS Runtime. Now, some of these things you're going to recognize,
for example, V8, here's the V8 engine and it
is handling the JavaScript. That's what it does.
Notice the event queue, different name but similar
to the message queue. The event loop is
also a part of this. In order to handle things
in the event queue. This part here live, you could be thought
as similar to the Web API is going to handle things that NodeJS needs to do. That is not done by JavaScript, is done by the environment
outside of it. So the V8 engine is
still single threaded, still has one call stack, but it can take advantage
of other things. And running on a server, there are a number of different
things that need to be done and that's going
to be handled here. Now know GIS does
have some commands that are similar to what
we see in the browser. For example, setTimeout,
set interval, both of those are available
and NodeJS as well, they're not handled
by the V8 engine, just like they're
not in a browser. They're handled over here. And so there are
some similarities. But because it is a
different environment, because the runtime
is different. It was handled in
different ways, but the concepts
are transferable. So once again, you
can read more about this in this article
if you choose to. But I did want to make the point of the event loop and
similarities between NodeJS and the runtime
environment handled in a browser. Alright, let's move
on to the next topic.
9. Exercise Start: Exploring Call Stack and Event Loop: So I wanted to make a
little fun exercise as a part of this section, a chance to explore
the call stack a bit and the event loop. Now, with all my courses, I always have exercises throughout them because
I think it's important for you to actually
do things in order to learn that doing of things needs to be on
your own at times. And so that's where
the exercises come in. The way I do those is I have an initial video
introducing the exercise. And then you go
ahead and try it. And then when you're ready,
you go to the next topic. And we go through that exercise. That's generally the structure. Sometimes they do things
a little bit different, but that's generally
the structure. So let's go ahead
and take a look at what I'd like you to
do for this exercise. Alright, the files
for the exercise, and specifically the
JavaScript file App.js. I've got some code here
and let me just explain it really quick and then I'll indicate what
I'd like you to do. So right here we're
creating an array, and we're creating an array
with 10 thousand elements. The number I've used
in the constructor, the array constructor
right there. And then we use the fill method of arrays to fill
that in with ones. And so basically it
creates an array with a length of 10 thousand that
has ones in all of them. That's what we're doing here. Then I have a little
function, I call it pop it. Basically all it
does is just pop off a value each time the function is called
from this array here. And then we invoke it. And notice we have recursion here because it checks
the length of the array. If the length is
still greater than 0, meaning there are still
items on that array, then it will call itself again, which will cause it to
pop off another item. That's recursion we're doing. And as you remember when
we did recursion before, we're able to
overflow the stack. And so what I'd like you to
do is see what number is required to cause
a stack overflow. If 10 thousand works
for you, then great. But it may not. And so just play with that
number of bids, kinda fun just to
see what's going to cause that to overflow. And then the second
part of the exercise, once you get that
stack overflowing, how can you change this? How can you cause this to use the event loop so that the
stack doesn't overflow. So kind of an interesting idea, taking advantage of something
that's available on the runtime environment so that we don't
overflow the stack, but we still can use
that same number that was overflowing the stack. So give, give that a try. Obviously, I haven't taught specific commands
for you to do this, although you've seen some
examples as we've been looking through different
concepts in this section. But give that a try
with what you know. And then when you're ready, go to the next topic and
we'll go through it.
10. Exercise End: Exploring Call Stack and Event Loop: Alright, let's take a look at this fun little
exercise here. So right now, 10 thousand, that's how many
is in this array. Let's see if this
causes a StackOverflow. So I'm gonna go ahead and serve this up and see what we get. So I'm going to jump
to the HTML file and then click Go Live. And then jumped to the console. Right now we're not seeing
any errors for StackOverflow. So that seems to
be working okay. So jumping back to
Visual Studio Code, I'm just going to
reduce the size of this a little bit
so we can go ahead and see the console log
while we play with this. So let's go up to,
let's go 10,500. Let's see what happens there. So I'm going to change that
number there, save it still. Okay. Let's go to 11 thousand. I'm going to save it. And I'm still not
getting any problems. So maybe we need
to jump up more. Let's go 13 thousand still. Okay, Let's go 15 thousand. And there we get an overflow. So I don't know what
the exact number is, but that wasn't really what
I want to accomplish here. I just wanted to give you
a chance to play with this stack overflow and see that eventually at some point, it will cause the stack
size to be exceeded. Then we get the air
uncaught range here. Alright, so there's the
air we're looking for. Now. How can we change this? So we can still keep this
number and still be able to run this recursively and pop off all these
items from the array. Well, in order to take
advantage of the event loop, we can use the web API, we can use setTimeout to actually invoke this
function again. Okay? So instead of
calling it recursive, recursively right away, we can use setTimeout to invoke it. And so the way we would do that, setTimeout, and then we
pass in the function. Now we don't include
the parentheses at this point because that will cause it to invoke right away. We just pass in the function
and then it will invoke it once the timer has expired. So we're gonna put
a 0 after that for 0 milliseconds we want
to invoke right away. And so here's our new setup. Let's go ahead and save that and see what happens down here. Notice we're not
getting the air. Let's go ahead and take
a look at the array, see how many are left. We're down to 13,600. So that's how many
has popped off. So obviously, since we're
using the event loop, we're using the Web
API with setTimeout. In order to pop these off. It's taking longer
to remove all of them because it has
to set up that timer. Then it puts
something in a queue. And then that item
from the queue is then placed in the call stack
and then it's popped off. And it's doing that
over and over again. So let's look at
it against him and we've reduced it to oh, we've got down 67
thousand or 6700 now. So it's moving through
them, but it's kinda neat. You can see it do this because it's doing
it so much slower. But notice it's not blocking. I can enter stuff here on the console and I'm
not blocked from doing other stuff in JavaScript. So that's the advantage of the event loop
working for us there. Take one more look, almost done. And by the time I press
Return, it was done. So it's now cleaned
off that array. So just a fun little exercise
to explore the call stack, an event loop a little bit. Alright, let's move
on to the next topic.
11. How JavaScript Evolves: As the JavaScript developer, it is important
to understand how JavaScript evolves and changes. Because that is something that is definite in the
JavaScript world. It is constantly evolving. When I first started using
JavaScript many years ago, it was nothing like the
language we have today. It almost feels like a
different language altogether. We can do so much
more with it now. To understand how
JavaScript evolves, we need to talk
about two things, ekman script and TC 39. First, let's talk
about ECMO script. Now. What is a script? I'm sure you've heard of it. It's battered around
all the time, basically as simply
a specification used by certain languages. It's standardized by
the ACM International, and that is where
the name comes from. Javascript is the most widely used implementation
back my script. So that's why it's entangled
with JavaScript so closely. But there are other languages
you've probably heard of. The fall of this Ekman
scripts standard. For example, Action Script, which is the language
behind flash that is based on the Ekman script
standard and J script which was done by Microsoft. That's also based on
that specification. Now, the first edition of the Ekman scripts standard
came about in June of 1997, and that was referred to as
Ekman script one or ES1. And since that time, each additional release has been that number has
been incremented. So ES x1, x2, x3, and so on. Now, when acme script
sixth was released, they started designating
the lease with the year. And so at that time, the release was technically
referred to as Ackman script 2015 because that's the year that Ekman scripts
six was released. However, ES6 has just stuck. And so people refer to that
as ES6 or ECMO script 2015. They go back-and-forth
between that, because the ES6 releases stuck. That particular release was a huge release with a number
of features for JavaScript. If you were in the JavaScript
world at that time, you will remember
how many things were added to JavaScript. A lot of things that
now make regular use of were added during
that particular release. Now, since that version
of the standard came out, there has been a new
release each year. And so we've had Ekman
script, 2016201718192020. Every year, a new
release has come out. A lot of that comes
from the fact that the Ekman scripts six
release was so huge. They didn't want another
release that big again. And so they're approaching the release is in a much
more manageable way. Now, who determines what
is in each release? Where does that all come from? Well, that has to
do with TC3 nine. So let's talk about that. Now. Tc 39 stands for
technical committee 39. And they are a committee
that evolves JavaScript. And its members are companies
such as browser vendors, that sort of thing have a
vested interest in JavaScript. The committee meets regularly and you can follow their minutes
online if you choose to. So in that sense,
it is transparent. Now in order for a feature to make it to maturity and become a part of a future Ekman
script standard release, that feature must go through several stages and we call
these stages of maturity. So TC3 dynein, the committee, manages these proposals through these stages until they are accepted as part
of the standard. So I want to talk about
those stages really quick. So stage one or stage
0, the first stage. But stage 0 is actually
submission stage. And this is just a
submission of a new feature, a proposal for a new feature. And this must come from a TC 39 member or someone who is considered
a TC 39 contributor. And basically it's a
document describing what the feature
is that they want. That stage 0. Stage one is the proposal stage. Now this is a formal
proposal for the feature. And this must have
a champion that as a part of that committee, someone who wants this
feature to be adopted. So that is stage one. Stage two is the draft stage. And this is really the
first version of what will be in the specification for
that particular feature. Once something gets to stage to its eventual inclusion
is much more likely. Now stage three is
the candidate stage. At this point, the proposal
is mostly finished and needs feedback from
implementations and from users. And then finally, stage
four is the finished stage. At this point, it's
ready to be included in the specification and most likely will be included in the next upcoming specification. But that's not
necessarily a guarantee. Through all these stages, these features are
still considered proposals and are not features until they are officially
included in the standard. Now, knowing these
stages can be important. For example, if you go
to a site such as this, and access upcoming features, which is done with this next button to find out what is supporting
and what isn't supporting. Notice how it's broken into the stages we just talked about. Here's the candidate stage, here's what's coming
up as a possibility in the next Ekman
script release. And you can see that
some browsers and some compilers are
already starting to support these
proposed features. You can see that over here, as you move down the
stages draft two, you see that fewer and
fewer implementations have already been done. And so since these vendors
Have a seat on the committee, they know what's coming up. They may be the champion of a particular
proposal, who knows, but they begin implementing
some of these things prior to them becoming a part of the
official specification. You can see we can even
go clear down to stage 0, not much going on there at all. So when articles or
sites like this are talking about proposals,
Ekman script proposals, they're talking about
things that are in one of these stages that have not been officially adopted
into the standard yet, but are moving in
that direction. So that is the process
tc threonine follows in order to update Ackman script
standard for JavaScript. Alright, let's move
on to the next topic.