What happens when JavaScript is initially executed?
Caspar Camille Rubin on Unsplash
Photo byRegardless of our knowledge of JavaScript, in some cases we probably never fully understood what happens under the hood when the code is initially executed. In order to understand what is going on behind the scenes I did some research, so this post is me sharing what I learned. I will do my best explaining this topic as clear as possible as I guide you through the following concepts:
- JavaScript Runtime Environment.
- JavaScript Engine.
- The Heap.
- The Call Stack.
- Web API Container.
- The Callback Queue.
- The Event Loop.
Before execution, JavaScript has to compile into code the computer can understand, and, as you might have guessed, the browser is the one doing the compiling job (with Node.js we can execute JS outside the browser, but in this article I am going to focus on JS inside the browser).
The JavaScript Runtime Environment
Each browser has a JavaScript Runtime Environment in which you can think about as a big container holding other smaller containers inside, these smaller containers are the WEB APIs made available to developers so they can build web apps, programs, etc. Some of these APIs are AJAX, the DOM tree, among others).
In addition to that, the JavaScript Runtime Environment has a JavaScript engine. Each browser has a different JavaScript engine. This article is based on the V8 JavaScript engine, the one Google Chrome uses.
Once Chrome receives our code, V8 does a quick scan to verify if we have any syntax errors, if it doesn't find any, it proceeds to read our code line by line in order to translate it into one the computer understands, that is, binary code.
Below you will see a graphic representation of how this JS Runtime Environment works.
Now I will proceed and explain each one of the steps metioned in the image above.
The Heap
As the JS engine encounters variables and function declarations in the code it stores them in the Heap.
The Call Stack
When the JS engine encounter function calls, it adds them to the Call Stack (as long as the stack is not processing other calls). If this function has variables, the JS engine sends them to the Heap, if it has other calls (function calls) it adds them to the top of the Stack, or if it is a timer or an AJAX call, it is sent to the Web APIs container.
Then it starts to execute the code within each function and at the end of each one, if no value was specified, it returns undefined by default, so, at this point, the function is removed from the Stack, and so on until The Stack is empty.
This shows us that Javascript is executed synchronously, in a single thread. It does one thing at a time, it analyzes a function, and once it finishes processing it, that function is removed from the Stack.
The Stack is a data structure that runs LIFO (Last in first out). No other function, but only the one at the top of the Stack, will be focused or active, and the motor will not move to the next function unless the one above is removed from the Stack.
Below you will find a video that exemplifies this procedure and links to other help resources that will help you understand these processes in detail.
Web API Container
If one of the calls is an event listener (such as a click, mouseover, etc.), HTTP / AJAX requests, or timer functions, these are sent directly to the Web API container and wait there until either a “click” event is triggered or the response of an AJAX call is received, or the time specified in the setTimeout has passed. Then, the callback functions of these (which are anonymous functions) are sent to the fourth and last container, the Callback Queue (the call queue).
The Callback Queue
As the callback functions are added in this container, which are organized in order of arrival (as specified in the previous point), they wait until the Stack is empty to be added to it, a at the same time, in the order in which they were added.
Unlike the Call Stack, the Callback Queue is a data structure that runs FIFO (First in First out). Therefore, the callback function that enters first, is the one that comes out first when it is its turn to move to the Call Stack.
The Event Loop
This guy is in charge of constantly watching the Call Stack checking if it's empty or not, and if the Callback Queue has any function on hold.
It is important to note that, regardless of whether the Stack and the Callback Queue are empty, the Event Loop will always be watching them, since at any time an anonymous function can come to the Queue from the Web API container, which would enter the Stack if it's empty.
Conclusion
So, after understading the above, you can agree with me that even thought sometimes JavaScript is apparently running asynchronously, it is not doing so since JavaScript can only handle one function at a time in the Stack, is because of the help of the Web API container, the Callback Queue and the Event Loop that it seems to be working asynchronously.
In order to get your head around this, you'll find this link very helpful, http://latentflip.com/loupe. I recommend watching the video first, it's a video where the author, Philip Roberts, talks about what happens when JavaScript runs.
"Loupe is a little visualisation to help you understand how JavaScript's call stack/event loop/callback queue interact with each other". Philip Roberts
What the heck is the event loop anyway? | Philip Roberts | JSConf EU