As a developer, it is often easy to focus on implementing a particular task or feature and ignore the inner workings of the language or platform we are using. This approach, known as declarative, allows us to quickly and efficiently complete our work without worrying too much about the underlying details.
However, while being declarative can be helpful in many cases, it is essential to have a deeper understanding of the inner workings of the language or platform we use. This understanding can help us create more innovative and groundbreaking solutions, as we can utilise the full capabilities of the language or platform to their full potential. In addition, having a deeper understanding of the inner workings of a particular subject can also help us to identify and troubleshoot problems more effectively and to make informed decisions about the design and implementation of our projects.
A JavaScript engine is a software program that executes JavaScript code. It is responsible for interpreting the code and performing the actions specified by the code.
Think of the Javascript engine as a starter motor. A starter motor is a small electric motor responsible for starting the car’s engine. There are many JavaScript engines available, each with unique features and capabilities. Some standard JavaScript engines include V8 (used in Google Chrome) and Spider Monkey (used in Mozilla Firefox).
The global execution context is the environment in which the code of a JavaScript program is executed. It is created when the JavaScript engine starts to execute the program, including the global object, the this value, and the default value for the undefined variable.
Imagine that a JavaScript program is like a car. The global execution context is like the car's engine. It is the part of the car that powers the entire vehicle and allows it to run.
Just like the global execution context includes the global object, the this value, and the default value for the undefined variable, the car's engine has various parts and components that work together to make the car run. These parts include the cylinders, the spark plugs, and the fuel system.
The global object in the global execution context is like the car's dashboard. It is a built-in object that provides access to many properties and methods available to the entire program, just like the dashboard provides access to the car's various controls and displays.
The this value in the global execution context is like the car's driver. It is a unique value that refers to the object that is currently executing the code, just like the driver is the person who is presently in control of the car.
The undefined variable in the global execution context is like a warning light on the dashboard. It is a special variable that is defined by default and has the value undefined, just like a warning light is a default feature on the dashboard and is used to indicate a problem or issue with the car.
The global execution context has access to all the variables and functions defined in the global scope, just like the car has access to all of its parts and systems. These variables and functions are referred to as global variables and global functions. They can be accessed from anywhere in the program, just like the various parts and systems of the car can be accessed from anywhere in the vehicle.
Now that we have some idea about the global execution context, We can understand how a javascript program executes
In JavaScript, a program typically runs in two phases: the creation phase and the execution phase.
During the creation phase, the JavaScript engine sets up the global execution context for the program. During this phase, the engine scans the code for function declarations and creates function objects for each. These function objects are stored in the global execution context's memory space, also known as the global memory.
Once the creation phase is complete, the engine moves on to the execution phase. Before executing the code, it first parses it and creates the AST from it.
Think of abstract syntax tree (AST) in JavaScript as the car's wiring diagram. A wiring diagram is a detailed diagram that shows the electrical connections and circuits in a car. It shows how all the various components and systems in the car are connected and work together.
Similarly, the AST is a detailed representation of the code in a JavaScript program. It shows the structure of the code and how all of the various elements of the code, such as variables, functions, and control structures, are connected and how they work together.
Just like the wiring diagram is essential for understanding how a car's electrical system works, the AST is necessary for understanding how a JavaScript program works. It helps developers understand the code's structure and flow and is often used by tools such as linters and debuggers to analyse and manipulate the code.
Once the creation phase is complete, the engine moves on to the execution phase. During this phase, the engine executes the code line by line, starting at the program's top and working its way down. As it executes the code, the engine may encounter function calls, which will create a new execution context for the function and push it onto the execution stack.
Think of the execution Phase as starting and driving the car. Just like the process of starting and driving a car involves turning the key, engaging the transmission, and using the pedals and steering wheel to control the car's movement, the process of executing a JavaScript program involves performing the actions specified by the code and using various language constructs and control structures to control the flow of the program.
Yes. the javascript engine has clever ways to optimise our javascript code to run faster. This is achieved by Just-In-Time (JIT) Compiler.
The Just-In-Time (JIT) compiler is a component of the JavaScript engine that operates during the execution of a program. It is responsible for optimizing the JavaScript code as it is being executed, so it operates in parallel with the program's execution.
The JIT compiler begins its work during the full code generation phase, where it translates the AST into machine code that can be executed directly by the processor. As the program is being executed, the JIT compiler continues to monitor the execution of the machine code and looks for opportunities to optimize it further. This process is known as incremental code generation.
The JIT compiler is able to optimize the JavaScript code in a number of ways, such as inlining functions, removing unnecessary code, and reordering instructions to improve performance. It is an important part of the JavaScript engine because it helps to improve the performance of the program by translating the code into faster, more efficient machine code.
"So that's it. That's the whole process of executing a simple JavaScript program, using the analogy of a car. First, the JavaScript engine receives the code and parses it, just like a car's fuel system receives fuel and processes it. The engine then converts the code into an abstract syntax tree (AST), similar to how a car's fuel system converts fuel into energy.
Next, the Just-In-Time (JIT) compiler takes over, acting like the car's engine. It begins by fully generating machine code from the AST, similar to how a car's engine converts fuel into energy to power the car. As the program continues to execute, the JIT compiler continually monitors the machine code and optimizes it further, similar to how a car's engine is continuously fine-tuned to run more efficiently.
And with that, the program has completed its execution, just like a car has reached its destination. Now it's time to grab my car keys and head home, knowing that my JavaScript program ran smoothly and efficiently thanks to the hard work of the JIT compiler. ”