Today, I began going through Anthony Alicea's JavaScript: Understanding the Weird Parts course again.
Once you know the basics of JavaScript and have learned how to write your own small programs, like the one's here on JSBeginner's 100 JavaScript Project List, this is a highly recommended course to learn better JavaScript.
Toni's content is slow, methodically, and most important, very helpful when trying to actually learn how JavaScript works “under the hood.”
The following are my notes:
Conceptual Aside: Syntax Parsers, Execution Contexts, and Lexical Environments
Syntax Parser – A program that reads your code and determines what it does and if its grammar is valid.
(Your code isn't magic. Someone else wrote a program to translate it for the computer.)
Lexical Environment – A lexical environment exists in programming languages in which where you write something is important.
(Where code is written and what surrounds it.)
Execution Context – A wrapper to help manage the code that is running.
(There are lots of lexical environments. Which one is currently running is managed via execution contexts. It can contain things beyond what you've written in your code.)
Conceptual Aside: Name/Value Pairs and Objects
Name/Value Pair – A name which maps to a unique value.
(The name may be defined more than once, but can only have one value in any given context. That value may be more name/value pairs.)
Example: A name value pair.
Address = '100 Main St.'
Object – A collection of name value pairs.
The simplest definition when talking about JavaScript.
Example: Address's value is an object and it has Apartment as a name value pair, where Apartment's value is an object.
Address: { Street: 'Main', Number: 100, Apartment: { Floor: 3, Number: 301 } }
The Global Environment and The Global Object
Global – The base execution context. Accessible to any and everything in your code.
When JavaScript runs, the base execution context creates a Global Object
and a variable called 'this'
.
In the browser, in the global object, this
and window
are the same.
In JavaScript when you create variables and functions that are not lexically inside a function, those variables and functions get attached to the global object.
Example:
var a = 'Hello World!'; function b(){ } //a --> "Hello World!" //b --> function b(){ } //window.a --> "Hello World!" //window.b --> function b(){ }
The JavaScript Execution Context: Creation Phase and Hoisting
Most programming languages executive their code one line at a time, top to bottom (assuming there are no conditional statements) but in JavaScript a function or a variable can be called even if it comes before it is declared.
The Execution Context has two phases:
Creation Phase – has the Global Object, ‘this', and the Outer Environment.
It also sets up memory space for variables and functions (hoisting).
This is why variables and functions can be called before they are declared, as long as they are declared in the same execution context.
Variables are set up in this phase but they are assigned a value of undefined
.
Functions are setup in their entirety.
Conceptual Aside: JavaScript and ‘undefined;
undefined
is not equal to not defined
in JavaScript.
Example:
console.log(a); <--a is not defined //If you try to use a variable that doesn't exist, you'll get a "Uncaught ReferenceError: a is not defined
" console.log(b); <-- undefined var b; //If you try to use a variable that does exist but is declared after its use, the variable will have the valueundefined
. var c = 2; console.log(c); <-- 2 //In this case, c is declared and defined (assigned a value) before it is used.
undefined
is actually a value, a keyword in JavaScript.
Never set your variables to a value of undefined.
Example:
var a = undefined <-- Don't do this. var b = null <-- Do this to represent the absence of a value instead of setting it to undefined.
Let JavaScript use it to set the value of undefined
and use null
instead to set the absence of a value.
If you set values to undefined you won't know if it's because you set or if the JavaScript engine set it.
The JavaScript Execution Context: Code Execution Phase
In the code execution phase, everything is set up by JavaScript (Global Object, this, Outer Environment, and memory space for variables and functions) and NOW your code (what you've written) is evaluated and ran line by line by the parser.
Conceptual Aside: Single Threaded, Synchronous Execution
Single threaded – one command at a time.
Synchronous execution – one at a time.
So, JavaScript being single threaded with synchronous execution means that only one command happens at a time, at one time.
JavaScript Function Invocation and The Execution Stack
Invocation – running a function. In JavaScript, we do this by using a parenthesis ().
When functions are invoked, a new Execution Context is created and placed “on top” on the Global Execution Content. This is the Execution Stack.
Whichever function is “on top” is the one that will currently be ran.

When the “top” function completes, it is “popped” off the stack.
It doesn't not matter which function is “on top”, lexically. The execution stack is based on the synchronous function calls.
When new functions are invoked, its own execution context is created as well (this, variable set, function hoisting, etc.).
JavaScript Functions, Context, and Variable Environments
Variable environment – where the variables “live” when created and how they relate to each other in memory.

In the above picture, each Execution Context has its own variables. Those variables are in “local scope.”
Each ‘myVar' is unique in the above case.
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); //output 1 2 undefined 1
JavaScript Scope Chain
Every Execution Context has a reference to its own outer “lexical” environment.
function a(){ var myVar = 2; b(); } function b(){ console.log(myVar); } var myVar = 1; a();

If JavaScript can't find a variable value in its Execution Context, it then goes “down” the scope chain to look in its outer reference environment for the value, which is based on where the function is written within the JavaScript file.
The “chain” is the link from one execution context down to its outer lexical environments.
function a(){ function b(){ console.log(myVar); } var myVar = 2; b(); } var myVar = 1; a();

JavaScript Scope, ES6, and let
Scope is where a variable is available in your code.
let can be used instead of var and allows the JavaScript engine to use block scoping.
When declaring a let variable inside a block, it's only available inside the block in which it was declared.
The following works:
var a = 10; var b = 8; if (a > b) { var c = true; } console.log(c); //This works true <--output
The following gets an Uncaught Reference error of ‘c is not defined':
var a = 10; var b = 8; if (a > b) { let c = true; } console.log(c); //This does not work Uncaught ReferenceError: c is not defined <--output
What About JavaScript Asynchronous Callbacks?
Asynchronous – more than one at a time.
JavaScript looks at the Event Queue and processes those events once the Execution Stack is empty.
If an event has a function call, the fuction will be placed on the stack and then the next event won't run until that function has been executed, emptying the execution stack once again.
This is explain further on MDN's JavaScript concurrency model and the event loop page.
Leave a Reply