JavaScript Quick Revision-1


  • Execution Context
  • Call Stack
  • Hoisting
  • Undefined vs not defined
  • window object
  • Loosely/weakly typed
  • Lexical Environment
  • Scope Chain
  • Temporal Dead zone (let & const)
  • Common Error Types
  • Block Scope
  • Shadowing

Execution Context and Call Stack:

Execution context is made of two components:

  • Memory or Variable Environment: Stores variables as Key-Value pairs
  • Code or Thread execution: Executes code line by line

There are two phases of JS program execution:

  • Memory Creation Phase: Memory is reserved as undefined for Variables. In case of functions, the entire function is copied (identified by the keyword ‘function’)
  • Code Execution Phase: In this phase, the actual value of the variable replaces the ‘undefined’ placeholder. When a function is invoked, a brand new Execution Context is created.

JavaScript maintains a Call Stack to manage the Execution Contexts. It maintains the order in which the execution contexts are created. The first one being, the Global Execution context, followed by other execution contexts created for respective functions in the program.


Hoisting is in simple terms, being able to access variables and functions even before they have been defined in the flow of the program.

  • For Variables, the value obtained is undefined.
  • Functions can be used even before they have been defined, in the same way as they would be used if called after the definition of the function in the code.

Hoisting is possible because the Execution context allocates memory in the first phase (before the code execution phase) for the variables and marks it as undefined. In case of functions, the entire function is stored in memory. Hence it can be use beforehand.

  • Arrow Functions: In case of arrow functions (as shown below), it behaves as a variable and not as a function. Hence it cannot be used before defining. It will throw a TypeError stating that the function is not defined.
var thisIsArrowFn = () => {console.log("Hello")}

Undefined vs Not Defined

  • When a variable has been allocated memory, “undefined” is the value reserved as a placeholder.
  • Not defined is when a variable has never been allocated memory (i.e it does not exist)

Note: To debug the code, create a .html file and a .js file and link it to the html file. You can write some sample code in the JS file. Open the html file in browser. Go to “Source” => add breakpoints => refresh the browser. Move through the breakpoints and look at the Scope => “Global” to see the value assigned by the Execution context before and during the code execution. You can also look at the Call Stack to see how Execution contexts are managed.

window object

It is a global object created by default in the Global Execution Context. ‘this’ points to ‘window’ at global level. If you try this === window, it will return true.

Loosely or Weakly typed

JS is said to be loosely typed or weakly typed because

  • It does not require the type of the variable to be defined before-hand.
  • It doesn’t enforce the constraint of types on the values.
  • Most importantly, it makes conversions between unrelated types implicitly.

Note: In a strongly typed language like Python, once a variable is assigned a value, it obeys a set of rules defined for that type and also how they interact with other types. For example, it wouldn’t allow an int to concatenate with a string (1+”1″ will throw an error)

Lexical Environment

A lexical environment is created along with the Execution Context. It contains the local memory of the given function plus the lexical environment of its parent (The function in which it resides). Hence the parent variables are always accessibly from the child functions.

Scope Chaining

Scope chaining is the sequence/chain of lexical environments. When a variable is not found in a given function’s memory, (where it is accessed) it searches for the same in the lexical environment of it’s parent and then parent of parent, until it reaches the Global Context who’s parent is Null. This sequence is called scope chaining.

Temporal Dead zone (let & const)

ES6 in 2015 introduced let and const. Before 2015, JS only had Global Scope and Function Scope. let and const have an additional restriction in comparison to var. It is mandatory to initialize them.

They are hoisted but are said to be in temporal dead zone. So, what is this temporal dead zone? The variable is said to be in temporal dead zone during the time between it’s memory allocation and its initialization.

  • The memory is allocated to the let and const variables but is stored in a different memory space. It is not attached to the this/window/global space. Hence it is not accessible until it is initialized.
  • If tried to access before initialization, it throws a ReferenceError stating that the variable you cannot access before Initialization.
  • If you try to initialize a let variable twice, it throws a SyntaxError stating that the variable is already declared.
  • In case of const, there is an additional layer of restriction. const variables have to be initialized upfront when declared (in the same line). Once initialized, you cannot modify the value of the variable.
  • const a; => will throw a SyntaxError which states: Missing initialization of const variable
  • If tried to reassign/modify, it throws a TypeError: Assigning to a const variable

let and const are usually preferred in comparison to var in order to write unambiguous, error free code.

Common Error Types

  1. Reference Error: When a variable is not found in the Memory space or is not defined or is in Temporal dead zone temporarily (in case of let and const).
  2. Type Error: Error specific to the type of the variable. Say, for example, while reassigning const.
  3. Syntax Error: When there is a missing syntax. Ex. let being assigned twice.

Block Scope

  • A Block is a set of statements written within curly braces({<>; <>}). It is also called a compound statement.
  • A block is used to write multiple statements where JS expects a single statement. In case of an ‘If’ statement, JS expects a single statement after if. A block can be used to replace a single statement with multiple statements.
  • Block scope: Variables and functions accessible within a block.
  • let and const are block scoped. i.e. they cannot be accessed outside the Block scope.
let x = 1;

if (x === 1) {
  let x = 2;
  console.log(x);  // expected output: 2
console.log(x);   // expected output: 1


Variables inside a block can shadow the ones outside the block, as shown below:

var a = 100;
   var a = 10;

In both the cases, a would be 10. As both are in the same global memory space, the variable inside the block shadows the one outside. A let and const variable cannot be shadowed. This is because, let and const have a separate scope (They are block scoped). Let us see an example:

let a = 10;
  let a = 100;

In the above case, the first one will log 100 and the second will log 10. So, they are no shadowed. They are placed in two separate memory locations:

Note: The above is true when let & const are used in functions and arrow functions too.

Illegal Shadowing: Trying to shadow a let or const variable using a var is illegal shadowing. It is not allowed and throws an error. SyntaxError: Identifier ‘a’ has already been declared.

This is because we are trying to reassign a let or const which is not allowed. Example below.

let a = 10;
  var a = 100;

It is absolutely okay if this is done in function scope instead of a block scope. This is because it resides in two separate memory location.

let a = 10;
function a() {
  var a = 100;


2 thoughts on “JavaScript Quick Revision-1

  1. Pingback: JavaScript Quick Revision – 3 – Reverie

  2. Pingback: JavaScript Quick Revision – 2 – Reverie

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s