JavaScript: setTimeout under the hood (technical literacy)
These are my notes taken during the ‘JavaScript Hard Parts` course on FrontendMasters given to us by Will Sentance. I am really glad I came across this course as it enlighten me what is really happening in JavaScript world.
Let’s take a look at this snippet, and understand how the JavaScript interpreter works.
function printHello() {
console.log(‘Hello’);
}
function blockFor1Sec(){
// blocks in the JavaScript thread for 1 second
}
setTimeout(printHello, 0);
blockFor1Sec();
console.log(‘Me first’);Javascript is single threaded, meaning that code is being executed synchroniously line by line.
As soon as we start running our code we create global execution context.
So what is happening first ?
First, we declare in memory named function printHello . Note that under the label printHello we store the whole function definition. Meaning if you would console.log(printHello) the browser will show you:
function printHello() {
console.log(‘Hello’);
}Then we are declaring (in memory) another named function blockFor1Sec . The function doesn’t have a body in this case. We just want to illustrate here that it will run for 1000ms. Let’s say it has a loop that has some heavy operations in it, which overall will take about 1s.
You might be wondering why the next line of code is not console.log(‘Hello’)? Only when a function is being called (has parenthesis after it, i.e. myFunction() ) we are getting into a function body.
Let’s recap and illustrate what we have done already. We have declared in memory two named functions printHello and blockFor1Sec. Note we are in global execution context still.
Our next line of code says us to call setTimeout with two parameters printHello and 0 ( the delay time until the function that has been passed as a first parameter will be called). More detailed information about setTimeoutfunction you can find on MDN.
setTimeout is a Timer feature of Web API. It is important to understand that this is not JavaScript function. When we call setTimeout Web API adds on two properties completed and onCompletion ( much more operations are happening under the hood, but for clarity, we will generalize it to two properties only). onCompletion property is a function that was passed to setTimeoutas the first parameter.
In our case we are delaying for 0 ms, therefore completed property will be true straight away.
However, theprintHello function will not be called, but will be pushed to the callback queue.
The event loop is constantly checking when our printHello function from callback queue can be pushed to the call stack.
Get Sveta Buben’s stories in your inbox
Join Medium for free to get updates from this writer.
[!] Once there is no synchronous code left in the global context, printHello function will be pushed to the call stack. But it is not the moment yet, because we still have some functions to invoke. We are left off with:
...
blockFor1Sec();
console.log(‘Me first’);Next blockFor1Secis being invoked. It creates its own execution context as well as its being pushed to the call stack, so JavaScript engine knows what execution context we are currently in. The function runs for 1000 ms.
Once blockFor1Secfinished execution it is being popped off the call stack and we are back into the global context. Meanwhile, garbage collector destroyed execution context of blockFor1Sec.
Next, ‘Me first’ is logged into a console.
Now when we have completed everything in the global execution context, it is time to push printHello to the call stack.
Calling printHello creates new execution context. Once it is done we are poping it off the call stack and garbage collector destroys its execution context.
Now we know how setTimeout function of Web API works. It is time to practise what we have learned 👩🏼💻
JavaScript interview question from Toptal
- What will be the output of the following code (speak through you solution).
for (var i = 0; i < 5; i++) {
setTimeout(function() { console.log(i); }, i * 1000 );
}2. In what order will the numbers 1–4 be logged to the console when the code below is executed? Why?
(function() {
console.log(1);
setTimeout(function(){console.log(2)}, 1000);
setTimeout(function(){console.log(3)}, 0);
console.log(4);
})();





