Home  >  Article  >  Web Front-end  >  Detailed explanation of the execution mechanism of js engine

Detailed explanation of the execution mechanism of js engine

小云云
小云云Original
2018-03-31 17:11:112963browse


This article mainly shares with you the detailed explanation of the execution mechanism of the js engine, hoping to help everyone.

First of all, please keep 2 points in mind:

  • js is a single-threaded language

  • The event loop in js is js Execution mechanism. A deep understanding of the execution of js is equivalent to a deep understanding of the event loop in js

Why is js single-threaded?

js was originally designed to be used in browsers, so imagine if js in the browser was multi-threaded.

Scenario description:

So now there are 2 processes, process1 process2. Since it is a multi-process js, they operate on the same dom at the same time. Process1 deletes the dom, and Process2 edited the DOM and issued two contradictory commands at the same time. How should the browser execute them?

Thinking about it this way, it should be easy to understand why js is designed to be single-threaded.

Why does js need asynchronous?

Scene description;

If there is no asynchronous in js, it can only be executed from top to bottom. If the parsing time of the previous line is very long, then the following code will be blocked. For users, blocking means ‘stuck’, which leads to a poor user experience.

So, there is asynchronous execution in js.

How does a single thread achieve asynchronous implementation?

Since JS is single-threaded and can only be executed on one thread, how to achieve asynchronous implementation?

It is through the event loop (event loop) that we understand the function of js Execution mechanism.

Event loop (1) in js

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);// 输出 1 3 2

In other words, the function in setTimeout is not executed immediately, but is delayed for a period of time and is executed after certain conditions are met. ,This type of code is called asynchronous code.

So, here we first know a classification method in JS, which is to divide tasks into: synchronous tasks and asynchronous tasks

According to this classification method, the execution mechanism of js is:

  • First determine whether js is synchronous or asynchronous. If it is synchronous, it will enter the main thread, if it is asynchronous, it will enter the event table

  • Asynchronous tasks are in the event The function is registered in the table. When the trigger condition is met, it is pushed into the event queue

  • The synchronization task will be executed after entering the main thread. It will not go to the event queue to check whether it is until the main thread is idle. There are executable asynchronous tasks, and if so, they are pushed to the main thread.

The above three-step loop execution is the event loop

So for the above example, can you describe their execution order?

console.log(1); // 同步任务,放入主线程中setTimeout(function() {
  // 异步任务,放到event table中,0秒后被推入到event queue中
  console.log(2);
}, 0);
console.log(3); // 同步任务,放到主线程中// 输出 1 3 2// 当1,3被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里面的函数。

Event loop(2) in js

Look at the next example:

setTimeout(function() {
  console.log("定时器开始");
}, 0);new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  console.log("执行then函数拉");
});
console.log("代码执行结束");

Use the js execution mechanism summarized before to analyze:

setTimeout 是异步任务,放在 event table中new promise是同步任务,被放到主线程中,直接打印console.log('马上执行for循环了');

.then里面的是异步任务,被放到event table中

console.log('代码执行结束') 是同步代码,被放在主线程中,直接执行。

So, the result is [execute the for loop immediately - the code execution ends - the timer starts - the then function is executed]?

After executing it personally, the result is not like this, but [execute the for loop immediately La—The code execution ends—The then function is executed—The timer starts]

So, is it the execution order of asynchronous tasks, not the order before and after, but other regulations? In fact, according to the asynchronous and synchronous The division method is not accurate

The accurate division method is:

  • macro-task (macro task): Overall code script, setTimeout, setInterval

  • micro-task (micro-task): Promise, process, nextTick

Detailed explanation of the execution mechanism of js engine

According to this classification method, js The execution mechanism is:

  • Execute a macro task. If a micro task is encountered during the process, put it into the event queue of the micro task

  • After the execution of the current macro task is completed, the event queue of the micro task will be checked and all micro tasks in it will be executed in sequence.

Repeat the above 2 steps, combined with event loop(1) event loop(2), to get a more accurate JS execution mechanism.

According to the mechanism just now, analyze example 2:

// 首先执行script下的宏任务,遇到setTimeout,将其放在宏任务队列中setTimeout(function() {
  console.log("定时器开始");
}, 0);// 遇到new promise直接执行new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  // .then方法,是微任务,放在微任务队列中
  console.log("执行then函数拉");
});
console.log("代码执行结束");// 宏任务执行完毕,查看本轮的微任务,返现有一个then方法。再去执行宏任务队列中的函数。

Talk about setTimeout

What does this setTimeout code mean? We generally say: After 3 seconds, setTimeout will be executed That function

setTimeout(function() {
  console.log("执行了");
}, 3000);

But this statement is not rigorous. The accurate explanation is: after 3 seconds, the function in setTimeout will be pushed into the event queue, and the tasks in the event queue (event queue) will only It will be executed only when the main thread is idle.

So only when (1) 3 seconds later (2) the main thread is idle, and both are met, the function will be executed after 3 seconds

If the main thread executes a lot of content, If the execution time exceeds 3 seconds, for example, if it is executed for 10 seconds, then this function can only be executed after 10 seconds.

In-depth understanding of the execution mechanism of the js engine

First of all, please keep 2 points in mind :

  • js is a single-threaded language

  • The event loop in js is the execution mechanism of js. A deep understanding of the execution of js is equivalent to a deep understanding of the event loop in js

Why is js single-threaded?

js was originally designed to be used in browsers, so imagine if js in the browser was multi-threaded.

Scene description:

那么现在有 2 个进程,process1 process2,由于是多进程的 js,所以他们对同一个 dom,同时进行操作,process1 删除了该 dom,而 process2 编辑了该 dom,同时下达 2 个矛盾的命令,浏览器究竟该如何执行呢?

这样想,js 为什么被设计成单线程应该就容易理解了吧。

js 为什么需要异步?

场景描述;

如果 js 中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着‘卡死’,这样就导致了很差的用户体验。

所以,js 中存在异步执行。

单线程又是如何实现异步的呢?

既然 JS 是单线程的,只能在一条线程上执行,又是如何实现的异步呢?

是通过的事件循环(event loop), 就理解了 js 的执行机制。

js 中的 event loop(1)

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);// 输出 1 3 2

也就是说,setTimeout 里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后,才去执行的,这类代码,我们叫异步代码。

所以,这里我们首先知道了 JS 里的一种分类方式,就是将任务分为: 同步任务和异步任务

按这种分类方式,js 的执行机制就是:

  • 首先判断 js 是同步的还是异步的,同步的就进入主线程,异步就进入 event table

  • 异步任务在 event table 中注册函数,当满足触发条件后,被推入 event queue

  • 同步任务进入主线程后一直执行,直到主线程空闲,才会去 event queue 中查看是否有可执行的异步任务,若果有就推入到主线程中。

以上三步循环执行,就是 event loop

所以上述例子,你是否可以描述他们的执行顺序了?

console.log(1); // 同步任务,放入主线程中setTimeout(function() {
  // 异步任务,放到event table中,0秒后被推入到event queue中
  console.log(2);
}, 0);
console.log(3); // 同步任务,放到主线程中// 输出 1 3 2// 当1,3被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里面的函数。

js 中的 event loop(2)

再看下一个例子:

setTimeout(function() {
  console.log("定时器开始");
}, 0);new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  console.log("执行then函数拉");
});
console.log("代码执行结束");

用之前总结的 js 执行机制去分析:

setTimeout 是异步任务,放在 event table中new promise是同步任务,被放到主线程中,直接打印console.log('马上执行for循环了');

.then里面的是异步任务,被放到event table中

console.log('代码执行结束') 是同步代码,被放在主线程中,直接执行。

所以,结果是 【马上执行 for 循环啦 — 代码执行结束 — 定时器开始啦 — 执行 then 函数啦】吗?

亲自执行后,结果居然不是这样,而是【马上执行 for 循环啦 — 代码执行结束 — 执行 then 函数啦 — 定时器开始啦】

那么,难道是异步任务的执行顺序,不是前后顺序,而是另有规定? 事实上,按照异步和同步的划分方式,并不准确

而准确的划分方式是:

  • macro-task(宏任务): 整体代码 script, setTimeout,setInterval

  • micro-task(微任务): Promise,process,nextTick

Detailed explanation of the execution mechanism of js engine

按照这种分类方式,js 的执行机制就是:

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的 event queue 中

  • 当前宏任务执行完成后,会常看微任务的 event queue ,并将里面全部的微任务依次执行完。

重复以上 2 步骤,结合 event loop(1) event loop(2) ,就是更为准确的 JS 执行机制了。

按照刚才的机制,分析例 2:

// 首先执行script下的宏任务,遇到setTimeout,将其放在宏任务队列中setTimeout(function() {
  console.log("定时器开始");
}, 0);// 遇到new promise直接执行new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  // .then方法,是微任务,放在微任务队列中
  console.log("执行then函数拉");
});
console.log("代码执行结束");// 宏任务执行完毕,查看本轮的微任务,返现有一个then方法。再去执行宏任务队列中的函数。

谈谈 setTimeout

这段 setTimeout 代码什么意思? 我们一般说: 3 秒后,会执行 setTimeout 里的那个函数

setTimeout(function() {
  console.log("执行了");
}, 3000);

但是这种说并不严谨,准确的解释是: 3 秒后,setTimeout 里的函数被会推入 event queue,而 event queue(事件队列)里的任务,只有在主线程空闲时才会执行。

所以只有满足 (1)3 秒后 (2)主线程空闲,同时满足时,才会 3 秒后执行该函数

如果主线程执行内容很多,执行时间超过 3 秒,比如执行了 10 秒,那么这个函数只能 10 秒后执行了

The above is the detailed content of Detailed explanation of the execution mechanism of js engine. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn