JavaScript | PART I

What you don’t know about JavaScript | Part I

Execution Context | Call Stack | Hoisting | Shortest JavaScript Program | Lexical Environment | Scope Chain

Mihiru Kongahage

--

wallpapertip

Stackoverflow survey statistics for 2020 show that JavaScript is the most commonly used programming language among developers for the eighth consecutive year. Popular front-end frameworks such as Angular, React, and backend frameworks like Node.js use JavaScript. The main focus of this article is to give you an in-depth idea of how JavaScript works behind the scenes. This article is a brief and easy-to-understand introduction to JavaScript concepts. So, I recommend you to explore more about these exciting concepts. Now, let’s get started.

JavaScript is a lightweight, interpreted, loosely-typed, prototyped-based, single-threaded, multi-paradigm language that supports object-oriented, imperative, and declarative with first-class functions. Confused? I know this is a chain of technical jargon. Let’s understand what these words really mean.

Lightweight — A programming language that uses a very small amount of memory with minimalist syntax and other features. These languages are easy to learn and use.

Interpreted — A language that need not be compiled into machine language instructions before execution. JS compilation happens at runtime.

Loosely-typed — Explicitly specifying types of variables and objects in JS is not required.

Prototyped-based — A style of OOP in which classes are not explicitly defined. Classes are derived by adding properties and methods to an instance of another class.

Single-threaded — JS executes codes in order (It will move to the next line after completing the previous line of code).

Multi-paradigm — Several programming paradigms such as imperative, declarative, functional object-oriented, and many more are characterized based on concepts they use in programming. JavaScript is a multi-paradigm language that supports object-oriented, imperative, and declarative paradigms.

First-class functions — A language that supports first-class functions means that it treats functions as variables. So, a function can be passed as an argument to another function, returned by another function, and can be assigned as a value to a variable.

Execution Context

Execution Context (EC) is the environment where the information of the currently executing code is held. EC contains two parts, Variable Environment, which stores all variables with their values, and Thread of Execution which includes code related to the particular context.

Initially, a Global Execution Context (GEC) will be created before the execution of the code. Then once a function is called, a Functional Execution Context (FEC) related to that function will be created, including the variables and the code. JS engine will create an EC (GEC and FEC) in two stages, the Creation phase, and the Execution phase.

Creation phase — In this phase, the JS engine will allocate memory to the variables and functions in the EC. For variables, it will store the spatial value undefined and the complete function code for functions in the allocated memory. If a function is declared as an arrow function, it will not store the function code, but it will be assigned undefined.

Execution phase — This is the phase where the code is executed. JS engine will run through the code, perform the specified calculations, and update the variables in the variable environment.

1 var x = 1;
2 var y = 2;
3 function add(a, b){
4 var z = a + b;
5 return z;
6 }
7 console.log(add(x,y))

Consider the above code snippet. In the creation phase, the GEC will be created, assigning undefined variables and function code itself to functions in the variable environment.

During the execution phase, the values for x and y variables will be replaced by 1 and 2. Then as soon as the execution hits the function call at line number 7, a separate FEC will be created for the add function.

Call Stack (Execution Context Stack)

For the methodical execution of ECs, the JS engine uses a stack called the execution context stack, also known as the call stack. Before the execution of the code, the JS engine will create GEC and will be pushed to the call stack. While in execution, if it finds a function call, it will create a new FEC and will be pushed to the call stack. From your data structures knowledge, you know that a stack follows the last in first out structure. So, the EC that pushes last will be executed first. After execution, the FEC will be popped from the call stack with a return value. Finally, GEC will be popped.

Hoisting

If you have ever used JS, it is most likely that you have seen the word undefined. What does undefined mean in JS?

Hoisting is a bit confusing concept where most people think that variable and function declarations are physically moved to the top of your code, but this is not what really happens. Instead, the variable and function declarations are put into memory before execution but stay exactly where you typed them in your code.

JS engine has the ability to access variables and functions before they are declared. Can you remember the creation phase of the EC? The JS engine will run through the code, allocating undefined spatial values to variables. So, it doesn’t matter in the execution phase even if the assignment of a variable is done before the declaration. Since the memory allocation and assigning the value undefined is done in the creation phase. In simple terms, the JS engine allocates memory to variables and functions before it starts executing the code.

1 console.log(`Just After Creation phase : ` + x);
2 x = 10;
3 console.log(`After Initialization : ` + x);
4 var x;
5 console.log(`Finally After Declaration : ` + x);

Can you guess the output of the above code snippet?

The first line will log the value of x just after the creation phase. So, the value will obviously be undefined. Then value 10 will be allocated to x even before the variable declaration and the value 10 will be logged on to the console. Finally, after the variable declaration value of x will be logged as 10.

Shortest JavaScript Program

Now, let’s see something interesting! Can you guess, the shortest JS program?

Yes, this is the shortest JS program, an empty file.

Now let’s see what happens when you run an empty JS file. From previous knowledge of EC, you know that a GEC is created before code execution. So, in this case, GEC is created, and also an object called Window is created at GEC with a whole lot of methods. Also, this keyword is created at the global space, which is pointed to the Window object.

Lexical Environment

The Lexical environment can be defined as the local memory of an EC with a reference to the lexical environment of its parent. The Lexical environment store the variable defined in that function during the execution of that function. It is important to understand what is a lexical environment to understand Closures in JS. Let me explain this using a code snippet.

1 function outer(){
2 var x = 1;
3 function inner(){
4 var y = 2;
5 console.log(x)
6 }
7 }

In the above code, the inner function can access variable y and also variable x. Local memory of inner function has y but not x. But inner function can access variable x because the lexical environment of the inner function has its local memory and also the lexical environment of its parent, which is the outer function in this case.

Scope Chain

By now you know what lexical environment is. Consider the code snippet below.

1  var z = 3;
2 function outer(){
3 var x = 1;
4 function inner(){
5 var y=2
6 console.log(y)
7 console.log(x)
8 console.log(z)
9 }
10 inner()
11 }
12 outer()

Inside the inner function, the variable y will be found in its local memory and will be logged on to the console. Then the value x will be checked inside its local memory. Since it is not available, it will get value from the lexical environment of its parent through the reference, and value x will be logged. Finally, it will try to find variable z in local memory and will check the lexical environment of its parent, and the value of z will be printed.

If a variable is not found in its local environment, it will try its parent environment using the reference to its parent lexical environment. If it is not found, it will try the parent environment of its parent. So this chain-like searching method is called the Scope Chain.

Is this all about JavaScript?, Absolutely not !!! There are many other important concepts that you need to know before you say that you know JavaScript. I suggest you to deep dive into these concepts and refer to the references mentioned. Trust me; you’ll find it more interesting.
Visit Part II

References

MDN Web Docs

Namaste JavaScript by Akshay Saini

--

--