How JavaScript Works? (JavaScript's Execution Context)

Zeeshan AliZeeshan Ali
4 min read

If you come from another language and JavaScript is your second programming language or you are just a curious student then some questions arise in your mind how is JavaScript code executed by the browser? whether it is synchronous or asynchronous and whether is it single-threaded or multi-threaded language. Today all of these questions will be answered.

So JavaScript code runs inside an Execution Context. You can think of execution context as a box and inside this box, there are two main components, one is a memory component that stores key-value pairs and the other is an execution component where the code is executed line by line.

Now the memory component is called Variable Environment which stores key-value pairs, which means any variable that you declare in your code is stored inside this. The code component of this box (execution context) is called the Thread of Execution. So how do these both work together to execute JavaScript Code?

When the code starts executing, first the variables are stored inside the Variable Environment and their value is set to undefined and if you declare a function with Function keyword then the whole function is stored inside it. The value that is temporarily assigned to the variables i.e. 'undefined' is itself a data type in JavaScript. After that, the thread of execution plays its role and starts executing the code line by line, one by one. When it sees a line in which a variable is declared, it assigns the value of it to the same identifier stored in the variable environment. Further, when the execution phase keeps going and it finds a function expression (not declaration with a 'function' keyword) it just assigns the whole function to its identifier in the variable environment or just passes on if it is declared with a function keyword.

Since the code is executed line by line, one by one, it answers some of our questions that whether JavaScript is synchronous and single-threaded. Yes, JavaScript is a single-threaded, synchronous programming language. But JavaScript can also handle asynchronous tasks using 'promises', 'callbacks', and 'async await'.

The most interesting thing happens when our code execution reaches a line where a function is invoked. When a function is invoked, another execution context is created inside the global execution context with the same two components which are Variable Environment and Thread of Execution. The arguments passed to the function are also stored inside the Variable Environment inside the execution context of the function. The code of the particular function is executed line by line. When the function returns a value, the control goes back to the Global Execution Context and returns the value to it.

When all code execution has been completed the whole Global Execution Context and smaller execution contexts of functions are deleted.

Now a question may arise, how these execution contexts creation and deletion are happening and not cluttering our program? The answer to that in JavaScript, there is a Call Stack in which all of these execution contexts are stacked one over another. At the bottom of it is Global Execution Context and when the whole code execution is done, the call stack becomes empty deleting all the execution contexts.

Thus storing the declared variables in Variable Environment make them accessible before they are declared inside the code. if you console log them before they are declared, they would return 'undefined'. For example, if you declare a variable with the 'var' keyword at line 2 and console log the variable at line 1, you would find that the log shows 'undefined'. This phenomenon is called Hoisting, which states that "Hoisting is a behavior in JavaScript where variable and function declarations are moved to the top of their containing scope during the compilation phase before the code is executed". This means that regardless of where declarations are made in the code, they are effectively 'hoisted' to the top of their respective scope.

But for the variables declared using the 'let' or 'const' keyword, there is a little exception. They are also hoisted but are not initialized with the value of 'undefined' in the variable environment, instead, there is a concept called "temporal dead zone" where the variables are hoisted but not initialized with 'undefined' until the actual declaration is encountered in the code.

Thus, in the same way, the function declaration is hoisted entirely which means that the whole function would be hoisted inside the variable environment. But there is a slight difference between function declaration and function expression where a function is assigned to a variable. Well, in that case instead of the whole function being hoisted, it is treated the same way as a variable and assigned a value of 'undefined' to it. Thus if you invoke a function before its expression inside the code, it would return an error that 'what you are invoking is not a function' because until then the JavaScript does not know whether it is a function or not because its value is just 'undefined' inside the variable environment.

In conclusion, understanding how JavaScript code is executed within the browser is essential for anyone delving into the world of programming. The concept of the execution context, with its variable environment and thread of execution, provides a solid foundation for comprehending the intricacies of code execution.

0
Subscribe to my newsletter

Read articles from Zeeshan Ali directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Zeeshan Ali
Zeeshan Ali

Hi there! My name is Zeeshan Ali, and I'm a passionate programmer and React Native mobile app developer. I've always had a fascination with technology and its ability to solve complex problems, which is what led me to pursue a career in software development. My love for React JS is what got me into front-end development, and I'm now working towards becoming a MERN stack developer. Aside from my day job, I enjoy contributing to open-source projects and giving back to the tech community. I'm always looking for ways to expand my knowledge and skills, and I'm currently learning Node JS to compliment my existing skill set. As a tech blogger on Hashnode, I'm excited to share my experiences, insights, and knowledge with fellow developers and enthusiasts. My goal is to create informative and engaging content that inspires and empowers others to pursue their passion for programming. Whether you're just starting out in the field or looking to advance your career, I hope to provide valuable resources and insights that can help you succeed. Thanks for stopping by, and I look forward to connecting with you on Hashnode!