Section 2: Execution Contexts and Lexical Environments
Syntax Parsers: A program that reads your code and determines what it does and if its grammer is valid. In other words, it's when programs, interpreters and compilers actually read your code, determines if the code is valid, and implements that syntax in a way that the computer can understand.
Lexical Environments: Where something sits physically in the code you write and what's around it. In other words, in programming languages, where you decide to write your code is very important.
Execution Contexts: A wrapper to help manage the code that is running. The wrapper can contain things beyond what you've written in your code.
Global: means not inside a function.
Creation Phase a.k.a. Global Execution Context when running code at the base level, the JS engine will automattically do the following:
Creates a global object. Your code will sit inside of this global object.
Creates a special variable called, "this". At the global level, "this" would equal the Global (window) Object.
A reference or link to the outer environment if there is one.
Hoisting, which setups up functions and creates a list of variables (but sets them all to "undefined"). Example code is below.
Then JS will run your code line by line (which includes adding values to variables, thus replacing the "undefined".
Name/Value Pair: A name which maps to a unique value. And a value can be more name/value pairs. Those are called objects.
Object: A collection of name/value pairs.
Code Example 10-01
Consider the following code:
var a = 'Hello World';
function b() {
console.log('Called b!');
}
b();
console.log(a);
console.log would report:
Called b!
Hello World
Now what if we did this?
b();
console.log(a);
var a = 'Hello World';
function b() {
console.log('Called b!');
}
console.log would report:
Called b!
undefined
What happened? JS engine will sweep through your code in this order:
Stores every function to memory, in their entirety.
Stores every variable names to memory, but not the value! Instead JS will set a placeholder called undefined.
JS engine will begin executing every line of code, which includes assigning values to variables.
This process is called hoisting.
undefined is more like a placeholder. JS is saying, "I'm going to set some memory aside for when you decide to place a value here."
Single Threaded: means one command is being executed one line at a time. JS behaves in a single threaded manner.
Synchronous: means one at a time. JS executes in a certain order, one line at a time. In JS, one thing is happening at a time.
Function Invocation and the Execution Stack
Invocation means running (or calling) function. As in, "Hey, run the function." We do this by using parenthesis, which will, invoke the function.
What happens when you invoke a function? Consider the following code:
function a() {
b();
var c;
}
function b() {
var d;
}
a();
var d;
Every time a new function is called, a new execution context is created. After Global Execution Context is created, the code above will run in this order, line by line:
a();
Which runs
function a()
Within
function a()
, it takes a detour to functionb();
function b()
is executed, then returns to finish upfunction a()
.function a()
is complete, then finally we get tovar d;
Function, Context, and Variable Environments
Variable Environment: where the variable lives. Consider the following code:
function b() {
var myVar;
console.log(myVar);
}
function a() {
var myVar = 2;
console.log(myVar)
b();
}
var myVar = 1;
console.log(myVar)
a();
console.log(myVar)
Here's the path:
var myVar = 1;
is recorded first.Execute
function a()
which recordmyVar = 2;
.Still inside
function a()
, we bounce tofunction b();
.Inside
function b();
,myVar
isundefined
.We're back outside of the function scope where
var MyVar
still equals1
.
In the console.log, you should see:
1
2
undefined
1
The Scope Chain
What console.log do you expect to see with the following code:
function b() {
console.log(myVar);
}
function a() {
var myVar = 2;
b();
}
var myVar = 1;
a();
You will get: 1
. But why? Each function has an outer reference based on the lexical location where the function is written. If a variable is not defined within a function, myVar will look for it's value in the outer reference, and keep digging out until it reaches the Global Execution Context. This act of searching is called the Scope Chain.
Consider this code. What will console.log report?
function a() {
function b() {
console.log(myVar);
}
var myVar = 2;
b();
}
var myVar = 1;
a();
Console log would return: 2
function b()
sits lexically, or physically, inside of function a()
. function b()
's outer reference is function b()
and that us where myvar
found it's value. So it stopped there.
Scope, ES6, And let
Scope: is where your variable is available in your code. And if it's truly the same variable, or a new copy.
What About Asynchronous Callbacks
Asynchronous: more than one at a time.
When a web page is loaded, simultaneous things are happening like JS creating the global stack, user events and HTTP requests. Events are saved in an Event Queue. After the stack is finished (or empty), the event queue (if any are relevant) are processed. That means any functions relying on a user event will be saved until the end.