JavaScript
Web
Have you ever wondered what exactly happens when you feed your browser some code? The process between parsing your code and executing it on the CPU is fascinating and often misunderstood. In this blog post, we’ll dive deep into this process to fill in the gaps in your understanding.
To start, let’s define what a JavaScript engine is. In simple terms, it’s a program responsible for:
If you want to score extra points, you might want to add that:
Imagine that we’re dropping an HTML file with some markup and a script tag containing the following JavaScript code into our browser:
Code
1function helloWorld() { return "hello world"; }
2
Here’s what happens step by step:
During the code execution step, a compilation is performed, which differs from Ahead-Of-Time compilation conducted before the code is run, thereby allowing for distinct code optimization tailored to each user or use case. This is one of the reasons JavaScript can be so performant. Here’s what happens:
In the end, all code must eventually run as machine code on the CPU. The key difference between interpreted machine code and optimized machine code is that the interpreted code runs without control from the engine, whereas optimized machine code is meticulously examined to execute only the necessary CPU instructions.
Regardless, whenever code is executed in JavaScript, it operates within an execution context, and the JavaScript engine creates and manages these contexts on a call stack.
In simplest words, an execution context is a place in the memory where the JavaScript code is evaluated and executed (or called/invoked - it means the same thing). Execution contexts are fundamental to JavaScript’s execution model. Here’s a breakdown:
Each execution context has two phases: the creation phase and the execution phase.
During the creation phase, the following environments are established:
In summary, during this phase:
Global execution context | Functional execution context |
---|---|
A global object (window for a browser or global for node) representing the executing code’s context is created in the Object environment record. | An arguments object containing references to the function’s parameters is created in the Declarative environment record. |
Memory in Object environment record is allocated for the variables and function declaration within the global execution context (defined globally). | Memory in Declarative environment record is allocated for the variables and function declaration within the function execution context (defined within the function). |
The this variable referring to the global object is created. | The this variable is created, referring to the global object or to an object to which the current code that’s being executed belongs. |
Variables are initialized as undefined (except let and const which will remain uninitialized). Functions are directly placed in memory. This explains why accessing a var variable before assigning a value results in undefined, while doing the same with let and const leads to a ReferenceError.
It is when hoisting takes place as well as where closures are created.
The first function to be executed is the one with its execution context at the top of the call stack.
Execution context gets popped off the stack when assignments to all the variables are done, and the code is executed (function is returned).
Finally, when the global execution context gets popped off the call stack, the program ends.
If a function is asynchronous or uses objects not provided by the JavaScript engine, the Web API, queue and event loop steps in, but that’s a story for another article so stay tuned!
Well, this is it. That is how JavaScript engines work at a high to medium level. While each concept could be explored in even greater detail, this should give you a solid foundation. Keep on coding and exploring the fascinating world of JavaScript!
For further reading on related topics, feel free to check out the below list:
Get a quote
“We are very happy with the outcomes and look forward to continuing to work with them on larger initiatives.”
Brian Grafola
CTO at Vibes