Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of execution context and execution Mechanism in JavaScript

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the example analysis of execution context and execution mechanism in JavaScript, which is very detailed and has certain reference value. Friends who are interested must read it!

Threads and processes

Before talking about the execution context in js and the js execution mechanism, let's talk about threads and processes.

What is a thread?

Officially speaking, threads are the smallest unit of CPU scheduling.

What is a process?

Officially speaking, a process is the smallest unit of CPU resource allocation.

The relationship between threads and processes

A thread is a running unit of a program based on a process. A popular interpretation thread is an execution flow in a program, and a process can have one or more threads.

Only one execution flow in a process is called single thread, that is, when the program is executed, the program paths are arranged in a continuous order, and the first must be handled before the latter will be executed.

Multiple execution flows in a process are called multithreading, that is, multiple different threads can be run simultaneously in a program to perform different tasks, that is, a single program is allowed to create multiple threads of parallel execution to complete their respective tasks.

The following author gives a simple example, for example, when we open QQ Music to listen to music, QQ Music can be understood as a process. In QQ Music, we can listen to songs while downloading here is multithreading, listening to music is a thread, downloading is a thread. If we open vscode again to write code, this is another process.

Processes are independent of each other, but some resources are shared among threads in the same process.

Life cycle of a thread

The life cycle of a thread goes through five stages.

New state: after you create a thread object using the new keyword and the Thread class or its subclasses, the thread object is in the new state. It maintains this state until the program start () is the thread.

Ready state: when the thread object calls the start () method, the thread enters the ready state. Threads in the ready state are in the ready queue and can run immediately as long as they get the right to use CPU.

Running state: if a thread in the ready state gets a CPU resource, it can execute run (), and the thread is in a running state. The thread in the running state is the most complex and can become blocked, ready, and dead.

Blocking state: if a thread performs methods such as sleep (sleep), suspend (suspend), wait (wait), etc., after losing the occupied resources, the thread goes from the running state to the blocking state. You can re-enter the ready state when sleep time is up or device resources are available. It can be divided into three categories:

Waiting blocking: the thread in the running state executes the wait () method, which puts the thread into the waiting blocking state.

Synchronization blocking: the thread failed to acquire the synchronized synchronization lock (because the synchronization lock was occupied by another thread).

Other blocking: when an I _ sleep O request is made by calling the thread's sleep () or join (), the thread enters the blocking state. When the sleep () state times out, join () waits for the thread to terminate or time out, or the thread returns to the ready state after IBG O processing is finished.

Dead state: when a running thread completes a task or other termination condition occurs, the thread switches to the terminated state.

Is js single-threaded or multithreaded

JS is single-threaded. As a browser scripting language, JS is mainly used to interact with users and to operate DOM. This determines that it can only be single-threaded, otherwise it will bring very complex synchronization problems. For example, suppose JavaScript has two threads at the same time, one thread adds content to a DOM node and the other thread deletes the node, which thread should the browser follow?

What is the execution context and the execution stack

When the JS engine parses to an executable code snippet (usually the function call phase), it does some pre-execution preparation. This "preparatory work" is called "execution context (execution context referred to as EC)" or execution environment.

Execution context classification

There are three execution context types in javascript, which are:

Global execution context this is the default or the most basic execution context. There is only one global context in a program, which will exist at the bottom of the execution stack throughout the life cycle of the javascript script and will not be popped up and destroyed by the stack. The global context generates a global object (in the case of the browser environment, the global object is window) and binds the this value to the global object.

Function execution context whenever a function is called, a new function execution context is created (regardless of whether the function is called repeatedly or not).

The Eval function execution context code that executes inside the eval function will also have its own execution context, but since eval is not often used, it will not be analyzed here.

What is the execution stack?

We mentioned earlier that js creates an execution context at run time, but the execution context needs to be stored, so what is used to store it? You need to use stack data structures.

Stack is a first-in-and-out data structure.

So to sum up, the execution context that is used to store code runtime creation is the execution stack.

Js execution process

When executing a piece of code, the JS engine first creates an execution stack to hold the execution context.

Then the JS engine creates a global execution context and push it to the execution stack. The process JS engine allocates memory to all variables in this code and assigns an initial value (undefined). After the creation is completed, the JS engine enters the execution phase, and the JS engine executes the code line by line, that is, assigning values to the variables that have previously allocated memory one by one (real value).

If there is a call to function in this code, the JS engine creates a function execution context and push it into the execution stack, which is created and executed in the same way as the global execution context.

When an execution stack is finished, the execution context pops up from the stack and then moves on to the next execution context.

Let me give you an example, if we have the following code in our program

Console.log ("Global Execution Context start"); function first () {console.log ("first function"); second (); console.log ("Again first function");} function second () {console.log ("second function");} first (); console.log ("Global Execution Context end")

Let's briefly analyze the above example.

First, an execution stack is created

Then a global context is created and the execution context is push into the execution stack

Start execution and output Global Execution Context start

When you encounter the first method, execute the method, create a function execution context and push it to the execution stack

Execute first execution context, output first function

When you encounter the second method, execute the method, create a function execution context and push it to the execution stack

Execute second execution context, output second function

After the execution of the second execution context, it pops up from the stack and enters the next execution context first execution context

First execution context continues to execute, outputting Again first function

After the execution of the first execution context, it pops up from the stack and enters the next execution context global execution context

The global execution context continues, outputting Global Execution Context end

Let's summarize it with a picture.

Okay. After talking about the execution context and the execution stack, let's talk about the execution mechanism of js.

Executive mechanism

When it comes to the execution mechanism of js, we need to understand synchronous and asynchronous tasks, macro tasks, and micro tasks in js.

Synchronous and asynchronous tasks

In js, tasks are divided into synchronous tasks and asynchronous tasks, so what are synchronous tasks and what are asynchronous tasks?

A synchronous task refers to a task queued on the main thread that can only be executed after the previous task has been executed.

An asynchronous task refers to a task that enters the "task queue" instead of the main thread (the task in the task queue is executed side by side with the main thread), only when the main thread is idle and the "task queue" notifies the main thread that an asynchronous task can be executed before it enters the main thread for execution. Because it is queue storage, it satisfies the first-in, first-out rule. Common asynchronous tasks are our setInterval, setTimeout, promise.then, and so on.

Event cycle

Synchronous and asynchronous tasks were introduced earlier, so let's talk about the event loop.

Synchronous and asynchronous tasks enter different execution "places" respectively, and synchronously enter the main thread. Only when the previous task is completed can the latter task be executed. Instead of entering the main thread, the asynchronous task enters the Event Table and registers the function.

When the specified thing is done, Event Table moves this function into Event Queue. Event Queue is a queue data structure, so it satisfies the FIFO rule.

If the task in the main thread is empty, it will go to Event Queue to read the corresponding function and enter the main thread for execution.

The above process is repeated over and over again, which is often called Event Loop (event cycle).

Let's sum it up with a picture.

The author briefly introduces an example.

Function test1 () {console.log ("log1"); setTimeout () = > {console.log ("setTimeout 1000");}, 1000); setTimeout () = > {console.log ("setTimeout 1000");}, 100); console.log ("log2");} test1 (); / / log1, log2, setTimeout 100, setTimeout 1000

We know that synchronous tasks are preferred before asynchronous tasks in js, so the above example outputs log1 and log2 first

Asynchronous tasks are executed after synchronous tasks are executed, so callback functions with a delay of 100ms give priority to output setTimeout 100s.

The callback function with a delay of 1000 milliseconds executes the output setTimeout 1000 after the meeting

The above example is relatively simple, I believe that as long as you understand the synchronous and asynchronous tasks mentioned above, there is no problem. Then I will give you another example, friends, to see what will be output.

Function test2 () {console.log ("log1"); setTimeout () = > {console.log ("setTimeout 1000");}, 1000); setTimeout () = > {console.log ("setTimeout 1000");}, 100); new Promise ((resolve, reject) = > {console.log ("new promise"); resolve ();}). Then () = > {console.log ("promise.then");}); console.log ("log2") } test2 ()

To solve the above problems, it is not enough to know synchronous and asynchronous tasks, we also need to know macro tasks and micro tasks.

Macro task and micro task

In js, tasks are divided into two types, one is called macro task MacroTask, and the other is called micro task MicroTask.

Common macro tasks MacroTask have

Main code block

SetTimeout ()

SetInterval ()

SetImmediate ()-Node

RequestAnimationFrame ()-browser

Common micro-tasks MicroTask include

Promise.then ()

Process.nextTick ()-Node

So macro tasks and micro tasks are involved in the above example, what is the order in which macro tasks and micro tasks are executed?

First of all, when the overall script (as the first macro task) starts to execute, all the code will be divided into synchronous tasks and asynchronous tasks, which will be executed directly into the main thread, asynchronous tasks will enter the asynchronous queue and then divided into macro tasks and micro tasks.

The macro task enters the Event Table and registers the callback function in it. Whenever the specified event is completed, Event Table will move the function to Event Queue.

The microtask also enters another Event Table and registers the callback function, which Event Table moves to the Event Queue whenever the specified event completes.

When the task in the main thread is finished and the main thread is empty, the Event Queue of the micro task will be checked. If there are any tasks, all will be executed. If not, the next macro task will be executed.

Let's sum it up with a picture.

We can easily get the answer by reading the examples of macro tasks and micro tasks in asynchrony.

We know that synchronous tasks are preferred before asynchronous tasks in js, so the above example outputs log1, new promise, and log2 first. It should be noted that the new promise is synchronized.

After the main code block is executed as a macro task, it will execute all the micro tasks generated by this macro task, so it will output promise.then

After all the micro tasks are executed, another macro task will be executed, and the callback function with a delay of 100ms will give priority to the output setTimeout 100s.

This macro task does not produce a microtask, so there are no microtasks to perform

To continue with the next macro task, the callback function with a delay of 1000 milliseconds optimally executes the output setTimeout 1000

So after the test2 method is executed, it outputs log1, new promise, log2, promise.then, setTimeout 100, and setTimeout 1000 in turn.

There are different opinions on whether the execution of js is macro task before micro task or micro task before macro task. The author's understanding is that if the whole js code block is regarded as a macro task, our js execution order is the macro task before the micro task.

As the saying goes, it is better to see than to practice. Here are two examples. If you can do both right, you can be regarded as having mastered the knowledge of js execution mechanism.

Example 1

Function test3 () {console.log (1); setTimeout (function () {console.log (2); new Promise (function (resolve) {console.log (3); resolve ();}) .then (function () {console.log (4);}); console.log (5);}, 1000); new Promise (function (resolve) {console.log (6); resolve () }) .then (function () {console.log (7); setTimeout (function () {console.log (8);}); setTimeout (function () {console.log (9); new Promise (function (resolve) {console.log (10); resolve ();}) .then (function () {console.log (11);});}, 100) Console.log (12);} test3 ()

Let's analyze it in detail.

First, the overall code block of js starts as a macro task, outputting 1, 6, and 12 in turn.

After the execution of the overall code block macro task, there is a micro task and two macro tasks, so the macro task queue has two macro tasks and the micro task queue has a micro task.

After the execution of the macro task, all the micro tasks generated by this macro task will be executed. Because there is only one micro task, 7 will be output. This micro task produces another macro task, so the macro task queue currently has three macro tasks.

No delay is set for the first execution of the three macro tasks, so output 8, this macro task does not produce a micro task, so there is no micro task to execute, proceed to the next macro task.

The execution of the macro task with a delay of 100 milliseconds, outputs 9 and 10, and produces a micro task, so the micro task queue currently has a micro task.

After the macro task is executed, all the micro tasks generated by the macro task will be executed, so all the micro tasks of the micro task queue will be executed, and the output 11

Macro tasks with a delay of 1000 milliseconds execute outputs 2, 3, 5, and generate a microtask, so the microtask queue currently has a microtask.

After the execution of the macro task, all the micro tasks generated by the macro task will be executed, so all the micro tasks of the micro task queue will be executed, outputting 4.

So the above code example will output 1, 6, 12, 7, 8, 9, 10, 11, 2, 3, 5, 4, whether the friends did it right?

Example 2

Let's slightly modify the above example 1 to introduce async and await

Async function test4 () {console.log (1); setTimeout (function () {console.log (2); new Promise (function (resolve) {console.log (3); resolve ();}) .then (function () {console.log (4);}); console.log (5);}, 1000); new Promise (function (resolve) {console.log (6); resolve () ) .then (function () {console.log (7); setTimeout (function () {console.log (8);});}); const result = await async1 (); console.log (result); setTimeout (function () {console.log (9); new Promise (function (resolve) {console.log (10); resolve ();}) .then (function () {console.log (11)) );}, 100); console.log (12);} async function async1 () {console.log (13) return Promise.resolve ("Promise.resolve");} test4 ()

What will be output from the above example? Here we understand async and await and the problem is easily solved.

We know that async and await are actually syntactic sugars of Promise, and all we need to know here is that await is equivalent to Promise.then. So the above example can be understood as the following code

Function test4 () {console.log (1); setTimeout (function () {console.log (2); new Promise (function (resolve) {console.log (3); resolve ();}) .then (function () {console.log (4);}); console.log (5);}, 1000); new Promise (function (resolve) {console.log (6); resolve () ) .then (function () {console.log (7); setTimeout (function () {console.log (8);});}); new Promise (function (resolve) {console.log (13); return resolve ("Promise.resolve");}) .then ((result) = > {console.log (result); setTimeout (function () {console.log (9)) New Promise (function (resolve) {console.log (10); resolve ();}) .then (function () {console.log (11);}); console.log (12);} test4 ()

Can you easily get the result by looking at the code above?

First, the whole js code block is executed as a macro task at the beginning, outputting 1, 6, and 13 in turn.

After the execution of the overall code block macro task, there are two micro tasks and one macro task, so the macro task queue has one macro task and the micro task queue has two micro tasks.

After the execution of the macro task, all the micro tasks generated by this macro task will be executed. So it outputs 7, Promise.resolve, 12. This micro task produces two more macro tasks, so the macro task queue currently has three macro tasks.

No delay is set for the first execution of the three macro tasks, so output 8, this macro task does not produce a micro task, so there is no micro task to execute, proceed to the next macro task.

The execution of the macro task with a delay of 100 milliseconds, outputs 9 and 10, and produces a micro task, so the micro task queue currently has a micro task.

After the macro task is executed, all the micro tasks generated by the macro task will be executed, so all the micro tasks of the micro task queue will be executed, and the output 11

Macro tasks with a delay of 1000 milliseconds execute outputs 2, 3, 5, and generate a microtask, so the microtask queue currently has a microtask.

After the execution of the macro task, all the micro tasks generated by the macro task will be executed, so all the micro tasks of the micro task queue will be executed, outputting 4.

So the above code example will output 1, 6, 13, 7, Promise.resolve, 12, 8, 9, 10, 11, 2, 3, 5, 4, whether the friends did it right?

Extended setTimeout (fn, 0)

With regard to setTimeout (fn), many friends still don't quite understand, isn't it clear that the delay time has not been set and should not be implemented immediately?

SetTimeout (fn) can be understood as setTimeout (fn,0), but it actually has the same meaning.

We know that js is divided into synchronous tasks and asynchronous tasks. SetTimeout (fn) is an asynchronous task, so even if you do not set a delay time, it will enter the asynchronous queue and will not execute until the main thread is idle.

I would like to mention again here, do you think the delay time we set after setTimeout, js will certainly be carried out according to our delay time? I don't think so. The only time we set is that the callback function can be executed, but whether the main thread is free or not is another matter. We can give a simple example.

Function test5 () {setTimeout (function () {console.log ("setTimeout");}, 100); let I = 0; while (true) {iTunes;}} test5 ()

Does the above example have to output setTimeout in 100 milliseconds? no, because our main thread has entered an endless loop and there is no room to execute tasks in an asynchronous queue.

GUI rendering

GUI rendering here that some small partners may not understand, later the author will publish an article on the browser will be described in detail, here is just a brief understanding.

Because the JS engine thread and the GUI rendering thread are mutually exclusive, the browser will render the page after the execution of one macro task and before the execution of the next macro task, in order to make the macro task and DOM task proceed in an orderly manner.

So the relationship between macro tasks, micro tasks, and GUI rendering is as follows

Macro tasks-> Micro tasks-> GUI rendering-> Macro tasks->. The above is all the content of the article "sample Analysis of execution context and execution Mechanism in JavaScript". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report