Understanding JavaScript: Notes 2


Back for the second session of Javascript: Understanding the Weird Parts.

Let’s get into it:

Hoisting, Creation Phase, and Undefined

So first things first, what is hoisting? In many programming languages, the order in which you write things matter. Things that appear later in the code happen later. If you define a function, then you have to call the function after. In JS, this isn’t quite the case.


a();

console.log(b);

function a () {

console.log("hello")

}

var b = 5;

 

In this case,

a()

will output hello and

console.log(b)

will show

undefined

. Why?

To answer this question, it’s important to understand that JS works in two stages. The first is the creation phase and the second is the execution phase. During the creation phase, the execution context is created in the creation phase. With is, the global object,

this

, and the outer environment are created. In addition, JS starts allocating memory for functions and variables. This is what is called hoisting. People sometimes explain hoisting as JS moving your function and variables to the top of your code, but that’s not true. If it was, then something like

var b = 5;

wouldn’t return undefined. Instead, what’s happening is that when the execution context is created, the JS compiler reads through the code and allocates memory to the functions and variables. So with functions already stored,

a()

can be called regardless of where it’s placed. The reason why

console.log(b)

is undefined is because when it’s hoisted, JS only takes the variable name and sets it as

undefined

.
On the topic of

undefined

, it’s important to note that this isn’t the same as not being defined aka reference error. If we forgot to declare

b

, and then we tried to

console.log

it, then it would throw a reference/not defined error. Undefined only happens when we declare a variable but we don’t set a value to it.

Execution phase

With everything being setup in the creation phase, the execution phase is pretty straightforward. This is where JS goes through your code, line by line, running it.

BIG WORDS // this is just a part of the course where the teacher takes the time to explain big sounding words
Single threaded: when you do one command at a time.

Synchronous: when you do one at a time or one line at a time

JS is single threaded, synchronous in it’s behavior. He mentioned about AJAX and asynchronous functions, but we’ll get to that later apparently =D.

Invocation: running a function. In JS, using (). By the way, every time a function is invoked, a new execution context is created and added to the stack.
In an example like this, when we say JS is single-threaded, synchronous, it means we will run a(), call b(), declare d, finish b (it pops off the stack), goes back to a(), declares c, finishes a (it then pops off the stack), returns back to global. One command at a time (finishing b before completing a), one line at a time (doing the line of code in b before doing anything else).

Variable environments: where variables live and their relation to each other. If vars of the same name are defined in various functions, then each function will create it’s own execution context with that var (when called) and that lives in that specific execution context, which is unrelated to the other vars of the same name.

The scope chain

Scope: where a variable is available in code

Chain: links to the outer environments (where a function is defined and what is the outer environment).

So if we have some code that looks like this, what is going to be in the console.log when

b

is called?

First JS goes into creation phase and creates the global execution context. In that,

myVar

,

function a

, and

function b

are set up (hoisted). Then it goes into execution mode.

myVar

is set equal to 1 and then

a

is called. When called, JS goes into creation mode again, setting up

myVar

in the function, and then goes back into execution mode. So

myVar (in a)

is set to 2 and then

b

is called. When called, (you guessed it) JS goes back into creation mode, sets up the outer environment and then goes into execution mode.  When when it runs the console.log, it doesn’t see anything in it’s immediate function scope. What happens is then it looks in its outer environment. Although the function was called in 

a

, it’s outer environment is where the function was defined, which is

global

and not

a

. There, it finds myVar, which has a value of 1 and that’s what gets console logged. So scope refers to where variables can be accessed. The global scope does not have access to

myVar in a

, because that doesn’t get setup until a is called and belongs to a different execution context. But functions that exist in other functions are part of a chain. So they have access to variables and functions that exist in their outer environments. And again, this is where a function is created (it’s lexical environment) NOT where a function is called.

let – is a new variable declaration in es6. It allows for block scoping. If

let a

is defined in a for loop, for example, then it exists only in that scope. Every time the for loop iterates, a new

a variable

will be created for that scope.

Asynchronous callbacks

asynchronous – more than one at a time.

The JS engine doesn’t exist in a vacuum. Usually, it’s run in the browser. So the browser has it’s own rendering engine and there could be other things like HTTP requests. These things can do things asynchronously, but the JS engine is a single-threaded, synchronous engine. So how does it handle asynchronous callbacks?

JS does one command, one line at a time. When it’s created, it creates the execution stack. If something happens in the browser that JS needs to look at or act upon, then it’s added to an event queue. ONLY when JS finishes running everything in the execution stack, does it start listening for things in the event queue and acting on it. In other words, the

clickHandler()

is only called after JS finishes what’s on the stack. After that finishes, then it can get to the HTTP request. So despite having asynchronous things happening outside of it, JS still takes them synchronously.

I’m still a little unclear on how various asynchronous call back things operate together though. Like if I request something from an api and at the same time while doing something with a click action. Because if I request something from an API, clicking requests can still happen on a site (usually). So if I think about, I’m guessing that when an API request is sent out, the stack is cleared, freeing JS to do other things in the queue, and when that api request sends something back it just gets added to the queue again and acted upon when the JS engine is free. If you know the answer, please let me know =D

Well that’s it for the second part of this class. Next up is

types

and

operators

.