The Complete JS Notes #3 đŸ§”

Baris Balli
5 min readJun 22, 2022

--

Welcome to the third article of my JavaScript notes.

In this article we will talk about : JIT compilation, Js Engine, AST, Web Apis, Call stack, EC

All the content is taken from Jonas Schmedtmann’s amazing course The Complete JavaScript Course 2022: From Zero to Expert!

Please purchase the course to understand the content, this is simply my summarized notes of the course.

You can define many variables at once like this

let scores, currentScore, activePlayer, playing;

JS is an interpreted or just-in-time compiled programming language

JS has 3 paradigms

  • Procedural Programming
  • OOP
  • Functional Programming

Procedural Programming is what we have done so far it put the code in a linear way in order to implement program’s logic.

Almost everything in JS is an object only primitive values are not objects.

JS is a first-class functions programming language. This means functions are treated as variables. We can pass them into other functions, and return them from functions. With this attribute it open the doors to Functional Programming.

We already used first class functions in our code for example when we add eventListeners.

Js Concurrency Model

Js is a single thread language however we want some tasks to longlast sometimes through whole application time.

If we put this in a single thread logic it blocks our way and doesn’t allow us to make other cool stuff.

So how does Js achieve this ? By using an event loop takes long tasks execute them in the background, and puts them back in the main thread once they are finished.

Js Engines

Every Js engine has 2 parts.

  • Call Stack: Where we read our code and do the job
  • Heap: Memory thet holds variables

Compilation vs Interpretation

In CS there are 2 type of languages

Compilation

Entire code is converted into machine code at once, and written to a binary file that can be executed by any computer.

Source Code -> Compilation -> Machine Code -> Execution -> Program Running

Machine code is a portable file.

The thing is you don’t have to execute your code immediately. It can happen way after the compilation.

Interpretation

Interpreter runs through the source code and executes it line by line

Source Code -> Execution Line by Line -> Program Running

The thing is while executing the program still needs to convert it to the machine code.

Program works immediatly after executed.

Important note here is interpreted languages are mostly quite slow.

Just-in-time (JIT) compilation

For a long time Js became a interpreted language and it worked quite fine like that but today web applications growed so big that nobody has that luxury. Imagine whenever you change location in google maps it takes 1s to load.

In JIT entire code is converted into machine code at once and executed immediatly

Source Code -> Compilation -> Machine Code -> Execution -> Program Running

Here the machine code isn’t a portable file and execution happens immediately.

Many people believes Js is still an interpreted language but it is JIT now.

Js Engine How Does That Work?

Fist Js Parce the source code. Parcing is a special way of reading.

It turns the syntaticly meaningfull pieses to AST (Abstract Syntax Tree) so it becomes like

Does this tree is related to the DOM?

No this tree has nothing to do with the DOM it is just here for the js

Allright now we parsed source code to AST now what?

We first compile the AST into machine code and then execute it immediately. Because JS uses JIT compilation.

So Parcing -> Compilation -> Execution right? Not so fast my impatient friend. because JS Engines has much more to offer.

For execution to be fast Js engines first compile AST to machine code in a very unoptimized way. Then during the execution it recompiles multiple times to optimize the code so last chart is

Parcing -> Compilation -> Execution

|_____|

Optimizes

Execution happens in the heap in a special thread and we can’t acces to that thread.

Bigger Picture: Js Runtime Environment

It has three parts

  • Js Engine : contains heap and the call stack
  • Web Apis like DOM, timers, Fetch Api these are not part of js
  • Callback Queue: click, timer, data click for example a call back function from DOM event listener

They all work in Event Loop (Remember that we use this to avoid single thread) For example when we click our call stack in the engine has a job to complete so it uses web APIs and js to make it.

What happens in Node.js runtime then.

In Node.js everything is actually quite similar only difference is the web APIs. In node we don’t have them but instead of them, we have C++ bindings and a thread pool.

What is an Execution Context?

Our execution has many steps.

1- Creation of global execution context ( for top level code )

It doesn’t include functions functions are being execute whenever they are called.

What is this execution context? It is the place where js code works it contains local variables and other things. So a js code can only work in an execution context.

Js code can have exactly one global execution context (EC).

2- Execution of top-level code. (Inside global EC)

Our top code now can be run in the Execution context so the machine code is send to the CPU to return the calculations.

3- Execution of functions and waiting for callbacks

A new EC is created for each functions. Also for the methods because they are function of the objects.

After finishing executing them our code starts to wait for callbacks.

All together make the call stack

What’s inside the Execution Context?

1- Variable Environment

  • Let, const and var declarations
  • Functions
  • arguments object

2- Scope chain

3- this keyword.

However arrow functions do not have arguments object and this keyword!!

This EC is generated during the “creation phase” right before the execution.

arguments object is an array of passed arguments to a function. They are available in all regular functions.

Call Stack Example

Call stack contains execution contexts.

const name = “Jonas”;const first = () => {let y = second();return y;}const second = () => {
}const x = first();

Cal stack for this will be:

second()

first()

Global

Then it gets empty from top to bottom.

--

--