JavaScript under the hood
original image by access-insurance.com

JavaScript under the hood

Hi there ??.

Further to my last post - in which I have intentionally shared a code snippet with a runtime issue, I'm going to talk about this "issue" in this article. I will demonstrate how JavaScript is working under the hood, and we will discuss it. I find this topic very important, and in my opinion, every front-end developer should spend some time getting familiar with and knowing the details. (the code snippet that I will discuss here is part of a snippet I have shared in my last post - click-me)

Let's start by saying that JavaScript runs on a single-threaded model, so only one task can be processed at any moment in time. Additionally, when JavaScript starts running, there is an execution context created.

But what is an Execution Context?

Simply put, an execution context is an environment that hosts your JavaScript code. You can think of an Execution Context as a container that stores variables and where our code is evaluated and executed.

So all JavaScript code runs in an environment, and these environments are called Execution Contexts. 

?? Execution Context is created when:

  • Our global code runs —  This is the root level of our code. The code that is not inside of any function is in the global execution context. When this context is created, it creates a global object, which is the window object (if we are running JavaScript on the browser, of course), and sets the value of this to equal to the global object. There is only one global execution context.
  • We call a function.
  • We use the eval() function.

?? Execution Context runs in two phases:

Creation phase - Variables and functions are stored in memory. The browser's engine (ex: V8 - Chrome, SpiderMonkey - Mozilla) does not execute assignment statements this phase. However, variables are initially set to a value called undefined. In contrast, there are some edge-cases that we will not discuss in this article in which values are not being initialized with the value of undefined (ex: a variable which declared with the let keyword).

Execution phase - The browser's engine executes lines of code. At this stage, the code can reference variables and functions placed in memory space during the creation phase.

?? To keep track of all execution contexts created, JavaScript has a concurrency model based on an event loop responsible for executing the code, collecting and processing events, and executing queued sub-tasks. Let's get to know the little parts of it:

Call stack - Call stack is a LIFO data structure consisting of active sub-routines in the computer program. When an execution context is created, it is pushed onto the stack. Once the execution context is done (reaches the last line of code OR the return keyword), the execution context will pop out of the stack.

Callback queue - The callback queue is a FIFO data structure, and it contains a list of operations that are not provided by JavaScript language. Asynchronous tasks, such as -promises, setTimeout and more. Those kinds of operations are provided by the platform which hosts our code, in this case - the browser (Web API). Once the call stack has no execution context running, then a process is popped-out from the callback queue and pushed into the call stack.

This queue can also be divided into two parts:

  • Task Queue - async operations such as setTimeout and setInterval.
  • Microtask Queue - async operations such as promises.

?? Important note: The microtask queue gets higher precedence than the task queue.

Event-loop - This is what puts this puzzle together. Each function that is being called will be pushed into the call stack, and when completed, the function will pop out of it. The event-loop is continuously keeping track of the call stack and the callback queue. When the entire execution has completed (including the global execution context) and the call stack is empty, it pushes the first processed callback function from the callback queue into the call stack.

**************************************************************************

This snippet will help me explain what is happening when JavaScript executes our code. You can take a look at it and try to figure out what is happening. (I have also added a promise to the original snippet from my last post just for connecting the little dots).


No alt text provided for this image

So what do we have here?

We have our global environment that hosts our variables, a promise declaration, a callback function that will be triggered when the promise is resolved, and a while loop. Inside of the while loop, we have some function calls running one after another, and at the end of the while loop block, we have a setTimeout with a callback function attached to it, the callback function will run 0 milliseconds after being processed.

Here is the catch, the code will never leave the while loop. The callback function attached to the promise will never get pushed into the call stack, likewise the setTimeout callback function. But why? 

Take a look at the following slide to see a snapshot of the event loop model in our case.


Since we attach everyThingIsFine variable state change to setTimeout's callback to break out of the while loop, this callback will be pushed into the call stack and executed when the global execution context (anonymous) is done running, and after the event loop will process and move the callbacks from the microtask queue into the call stack. So this callback function is waiting in the task queue and the while loop is still iterating without meeting the everyThingIsFine variable state change. The while loop condition will always be equal to - true, and we end up with an infinite loop.

I hope that this article will help you look at the code you are writing in another perspective, and that you will find this useful and hopefully write better code!

If you have anything to share, go for it! Feel free to DM me if needed. ????

Deijah W.

Senior GRC Analyst (Global Scope) #AI Enthusiast #GRC #??

4 年

Great article Lior! Very informative ????

Itay Gershman

Software Engineer at Wix.com

4 年

Lior Agami congrats on your second article brother! Your explanation really helped me to understand better how js works! Thank you, and keep it up??

要查看或添加评论,请登录

社区洞察

其他会员也浏览了