Javascript engines are programs that convert Javascript code into native machine code. These engines are embedded into the browser for runtime compilation and execution of the code. Google chrome uses V8 engine, Safari uses JavaScriptCore, and Firefox uses SpiderMonkey. To transform and run code faster, modern javascript engines use Just In Time (JIT) compilation, which is a combination of both interpretation and compilation.
How JS Engine Works

Parser
When Javascript code is executed, the engine first parses the code and breaks it down into token. These tokens are then converted into Abstract Binary Tree: a tree representation of the source code. AST Explorer is a tool that shows how code is converted into AST.
Interpreter
The interpret in V8 is called Ignition. The interpreter reads and translates the JavaScript files line by line on the fly, based on the generated AST. It produces unoptimised bytecode.
Profiling and Optimisation
The JavaScript compilers run feedback and collect profiling data for the code being executed. It looks for code that is hot: code that is run quite often or on which most of the exeuction time is spent. This code goes through optimizing compiler. It then generates optimised machine code that will be replaced for execution. V8 uses an optimising compiler called TurboFan. Turbojet can optimise the bytcode, produced by the Interpreter, in the background as the application runs.
Call Stack and Heap

A JS Engine consists of two components:
- Call Stack
- Heap
The heap is where objects are stored and memory allocation happens. Call stack keeps track of where the code is currently being executed using execuction contexts. When a function starts executing, its execution context is pushed on top of the stack and when it finishes execution, it is popped off the stack.
Execution Contexts
Execution context is an environment in which a piece of javascript code is executed. It stores all the necessary information like variables, functions and objects to execute the code.
Global Execution Context
It is the default execution context in which code starts execution and every Javascript code has exactly one global execution context. Global execution context is popped off the call stack when the entire programs finishes execution.
Functional Execution Context
Each function has its own execution context. When executing the code, if JS finds a function call, it creates a new execution context for that function and this execution context is pushed on top of the call stack. Functional execution context has access to the global execution context.
What is inside an Execution Context?
Variable Environment
Variable Environment consists of the following information:
- let, const and var declarations
- Functions
- Arguments object (not in arrow functions)
In the creation phase, the code is scanned for variable declarations, and for each variable, a new property is created in the variable environment. This is called hoisting and this allows some types of variables accessible in code before they are declared. But hoisting doesn’t work the same way for every type of variables:
- Function declarations are hoisted and initialised with the value of the actual function.
- Declarations that are made using var are hoisted and initilaised with a default value of undefined. Trying to access any variable declared with var before it is defined, will not result in an exception and will have a value of undefined.
- Declarations made using let and const are not initialized as part of hoisting and they remain in Temporal Dead Zone(TDZ). TDZ for every variable defined with const/let starts at the beginning of its scope until the line in which they are defined. Trying to access any variable declared with let/const before it is defined results in an exception.
- Hoisting of function expressions and arrow functions depends on if they were created using var or let/const.
Scope Chain
Every scope has access to all the variables from its outer scope. This chain of reference is what we call a scope chain. This is the reason we can access global variables from local scopes.
thiskeywordthisvariable is a special variable that is created for every execution context and its value depends on how a function is called.- When used in methods,
thispoints to the object that is calling the method. - When a function is called as a regular function call,
thiswill be undefined in strict mode. If not in strict mode, it will point to the window object. - Arrow functions do not have their own
thiskeyword. It inherits from its parent function or surrounding function: lexical this keyword. If the parent scope of the arrow function is global scope, its value will be window object. - When a function is called in an event listener,
thiswill point to the DOM element that the handler is attached to.
- When used in methods,
