An overview of the
Almost everyone has heard of the V8 engine concept, and most people know that JavaScript is single-threaded or that it uses callback queues.
In this article, we’ll cover these concepts in detail and explain how JavaScript works. By understanding these details, you can take advantage of the apis provided to write better, non-blocking applications. If you’re new to JavaScript, this article will help you understand why JavaScript seems so “weird” compared to other languages. If you’re an experienced JavaScript developer, hopefully this will give you some new insights into JavaScript runtime, although you probably use it every day.
JavaScript engine
The most popular JavaScript engine, of course, is Google’s V8 engine, which is used in Chrome and Node. Here’s a simple diagram to illustrate their relationship:
- Memory heap: This is where memory allocation occurs
- Call stack: This is where your code is executed
The runtime
Some browser apis are often used (e.g., setTimeout), but these apis are not provided by the engine. So where did they come from? It’s actually a little bit more complicated.
Then we have such popular event loops and callback queues.
The call stack
JavaScript is a single-threaded language, which means it has only one call stack, so it can only do one thing at a time. The call stack is a data structure that keeps track of where we are in the program. If we run a function, it puts it at the top of the stack. When you return from this function, it pops the function off the top of the stack, and that’s what the call stack does. Let’s take a look at the following example:
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
Copy the code
When the program starts executing, the call stack is empty. Then, the procedure is as follows:
This makes it clear how the stack trace is constructed and what the state of the stack is when an exception occurs. Let’s take a look at the following code:
function foo() {
throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
foo();
}
function start() {
bar();
}
start();
Copy the code
If this happened in Chrome (assuming the code was in a file named foo.js), the following stack trace would be generated:
“Stack overflow”
function foo() {
foo();
}
foo();
Copy the code
When our engine starts executing this code, it starts with function foo. Then this is a recursive function and starts calling itself without any termination conditions. Therefore, with each step, the same function is added to the call stack again and again. And then it looks something like this:
Concurrency and event loops
What happens when function calls in the call stack take a lot of time to process? For example, suppose you want to do some complicated image transcoding in your browser using JavaScript.
You may ask? What kind of question is that? In fact, the problem is that when the call stack has functions to execute, the browser can’t do anything, it gets jammed. This means the browser can’t render, can’t run other code, it’s stuck. This can be a problem if you want to make the UI smooth in your application.
And it’s not the only problem: once your browser starts processing the many tasks in the call stack, it may stop responding for quite some time. Most browsers do this, reporting an error asking you if you want to terminate the Web page.
That’s not the best user experience, is it?
So how do you execute complex code without blocking the UI so that the browser doesn’t become unresponsive? The solution is asynchronous callbacks. See this article: How to write optimized code in V8.
juejin.cn/post/684490…