console.log isn’t in the JavaScript language
Don’t take my word for it — RTFM!
console.log
is probably one of the most used commands by JavaScript beginners and veterans alike. But it isn’t part of the JavaScript Language itself. Don’t believe me? Check out the ECMAScript® 2015 Language Specification.
Now that I have piqued your interest because you didn’t find a single mention of console
in the ES6 Language Specification, read on.
Some of you might already know this, but what is called JavaScript on the Browser/Server, it is usually the JavaScript Environment. And this Environment is hardly just the Javascript Language Runtime (running on Javascript Engine i.e. V8 on Chrome and NodeJS, SpiderMonkey on Firefox, JavaScriptCore on Safari).
JavaScript Environment = JavaScript Runtime + Event Loop + External API + Callback Queue
Note: The Event Loop can be within the JavaScript Engine depending on the implementation
Theconsole
object is a Web API provided by the Browser to the JavaScript Engine, much like DOM, Fetch, History, Service Workers and Web Storage APIs. This makes perfect sense when you consider the fact that as a language, JavaScript runs on various environments browser and server-side environments, each with its own console
implementation.
The parts of JavaScript that are standard across all environments are detailed in the ECMA Specs (primitives, data types, language grammar and syntax, arithmetic and logical operations, built-in objects and functions, etc.). This means that while Array.isArray()
is built into JS, setTimeout()
and console
aren’t.
Let’s look at what the implementation of console
looks like across various environments:
The Node implementation has a couple of more methods (markTimeline
, timeline
, timelineEnd
) than the Chrome implementation though both environments implement the same ECMA Specs. On Firefox, console
will be further different from the two above.
Why is this important? To understand the workings of JavaScript, you need to have a grasp on how the language interacts with the environment it is embedded in.
In fact, JS is a fundamentally single threaded, synchronous language.
Any parts that are asynchronous (setTimeout
, setInterval
etc.) are implemented by and work via. the execution environment.
On the Browser, JavaScript execution looks something like this (courtesy Loupe by Philip Roberts). Note that ‘JavaScript’ or V8 is confined to the box titled ‘Call Stack’ on the left. Web APIs and the Callback Queue are both components of the Browser environment.
What is visualized above is the JavaScript Concurrency Model, or ‘How single-threaded synchronous JavaScript executes multiple (seemingly) concurrent asynchronous operations’. This also explains the infamous JavaScript interview question of why the below code
console.log('First');setTimeout(() => console.log('Second'), 0);console.log('Third);
prints
First
Third
Second
and not
First
Second
Third
JavaScript executes every command synchronously, one after the other. Any statement that has a callback function (like the
setTimeout
) is treated no differently, but the callback function is pushed to the callback queue.
Because we now know that setTimeout
is a Web API, it easier to understand that it triggers an external timer on the browser outside the JavaScript Runtime. While it may seem like JavaScript ‘revisits’ the point of execution at a later point in time, what actually happens it this:
- …..
- Event Loop continuously checks for non-empty Callback Queue (returns false)
- V8 pops
setTimeout
function from Call Stack and executes it - The execution notifies V8 to call the Web API to start the external timer (ET). ET starts.
- Event Loop continuously checks for non-empty Callback Queue (returns false)
- V8 pops any other frames in the Call Stack and executes them.
- …..
- ET runs out
- Web API pushes callback function (cbFn) into Callback Queue
- Event Loop continuously checks for non-empty Callback Queue (returns cbFn)
- Event Loop pushes cbFn into Call Stack
- V8 pops cbFn from Call Stack i.e. executes it
- Event Loop continuously checks for non-empty Callback Queue (returns nothing)
- …..
And now we know how synchronous, single-threaded JavaScript — runs asynchronous operations. The magic sauce is external APIs.
Happy coding!