Home  >  Article  >  Web Front-end  >  Detailed introduction to JavaScript operating mechanism (code example)

Detailed introduction to JavaScript operating mechanism (code example)

不言
不言forward
2019-03-05 13:45:091839browse

This article brings you a detailed introduction to the JavaScript operating mechanism (code example), which has certain reference value. Friends in need can refer to it, I hope it will be helpful to you.

1. Introduction

This article introduces the JavaScript operating mechanism. This part is relatively abstract. Let’s start with an interview question:

console.log(1);
setTimeout(function(){
console.log(3);
},0);
console.log(2);
请问数字打印顺序是什么?
复制代码

This question It seems very simple, but if you don’t understand the running mechanism of JavaScript, it is easy to get the wrong answer. The answer to the question is to output 1 2 3 in sequence. If you have any doubts, there is a detailed explanation below.

2. Understand the concept of single-threading in JS

One of the major features of JavaScript language is single-threading, that is to say, only one thing can be done at the same time. . So why can't JavaScript have multiple threads? This can improve efficiency. JavaScript is single-threaded, depending on its purpose. As a browser scripting language, JavaScript's main purpose is to interact with users and manipulate the DOM. This determines that it can only be single-threaded, otherwise it will cause very complex synchronization problems. For example, suppose JavaScript has two threads at the same time. One thread adds content to a certain DOM node, and the other thread deletes the node. In this case, which thread should the browser use? Therefore, in order to avoid complexity, JavaScript has been single-threaded since its birth. This has become a core feature of the language and will not change in the future.

3. Understanding task queue (message queue)

Single thread means that all tasks need to be queued, and the next task will not be executed until the previous task is completed. If the previous task takes a long time, the next task will have to wait. The designers of the JavaScript language realized this problem and divided all tasks into two types, one is synchronous task (synchronous) and the other is asynchronous task (asynchronous). Synchronous tasks refer to tasks queued for execution on the main thread. The next task can only be executed after the previous task is executed; asynchronous tasks refer to tasks that do not enter the main thread but enter the "task queue". Task, only when the "task queue" notifies the main thread that an asynchronous task can be executed, will the task enter the main thread for execution. Asynchronous tasks include macro tasks and micro tasks (which will be highlighted later). Next, we will illustrate the difference between synchronous tasks and asynchronous tasks through two examples:

console.log("A");
while(true){ }
console.log("B");
请问最后的输出结果是什么?
复制代码

If your answer is A, congratulations on the correct answer. Because this is a synchronous task, the program is executed from top to bottom. When encountering the while() infinite loop, the following statements cannot be executed.

console.log("A");
setTimeout(function(){
console.log("B");
},0);
while(true){}
请问最后的输出结果是什么?
复制代码

If your answer is A, congratulations, you now have knowledge of the js running mechanism. A brief acquaintance! The setTimeout() in the question is an asynchronous task. No asynchronous tasks will be executed until all synchronous tasks are executed. This will be explained in detail below.

4. Understand Event Loop

The operating mechanism of asynchronous execution is as follows:

  • All synchronous tasks are executed on the main thread, forming An execution context stack.
  • Besides the main thread, there is also a "task queue". As long as the asynchronous task has running results, an event is placed in the "task queue".
  • Once all synchronization tasks in the "execution stack" have been executed, the system reads the "task queue" to see what events are in it. Those corresponding asynchronous tasks end the waiting state, enter the execution stack, and start execution.
  • The main thread keeps repeating the third step above.

The main thread reads events from the "task queue". This process is cyclic, so the entire operating mechanism is also called Event Loop. As long as the main thread is empty, it will read the "task queue". This is the running mechanism of JavaScript. This process will cycle over and over again. The picture below illustrates this point well.

Detailed introduction to JavaScript operating mechanism (code example)

5. Which statements will be put into the asynchronous task queue and the timing

Generally speaking, there are the following four types of statements Put into asynchronous task queue:

  1. setTimeout和setlnterval
  2. DOM事件
  3. ES6中的Promise
  4. Ajax异步请求

javascript 代码运行分两个阶段

1、预解析---把所有的函数定义提前,所有的变量声明提前,变量的赋值不提前

2、执行---从上到下执行(按照js运行机制) 至于放入异步任务队列的时机,我们通过 setTimeout的例子和Ajax例子来详细说明:

例题1
for (var i = 0; i < 5; i++) {
setTimeout(function() {  
 console.log(i);  
  }, 1000);
}
请问最后的输出结果是什么?
复制代码

for循环一次碰到一个 setTimeout(),并不是马上把setTimeout()拿到异步队列中,而要等到一秒后,才将其放到任务队列里面,一旦"执行栈"中的所有同步任务执行完毕(即for循环结束,此时i已经为5),系统就会读取已经存放"任务队列"的setTimeout()(有五个),于是答案是输出5个5。

上面也提到,在到达指定时间时,定时器就会将相应回调函数插入“任务队列”尾部。这就是“定时器(timer)”功能关于定时器的重要补充

定时器包括setTimeout与 setInterval 两个方法。它们的第二个参数是指定其回调函数推迟/每隔多少毫秒数后执行。

对于第二个参数有以下需要注意的地方:

当第二个参数缺省时,默认为 0;

当指定的值小于 4 毫秒,则增加到 4ms(4ms 是 HTML5 标准指定的,对于 2010 年及之前的浏览器则是 10ms);也就是说至少需要4毫秒,该setTimeout()拿到任务队列中。

例题2
$.ajax({
url:&#39;xxxxx&#39;,
success:function (result){
console.log("a")
   }
})

setTimeout(function (){
console.log("b")
},100)

setTimeout(function (){
console.log("c")
})

console.log("d");

 Detailed introduction to JavaScript operating mechanism (code example)

ajax加载完成时才会放入异步队列,至于这段时间不确定,所有有两种情况:①大于100ms,最后的结果是 d c b a ;②小于100ms,最后的结果便是d c a b。

六、微任务(Microtask)与宏任务(Macrotask)

我们上面提到异步任务分为宏任务和微任务,宏任务队列可以有多个,微任务队列只有一个

  • 宏任务包括:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering。
  • 微任务包括: new Promise().then(回调), process.nextTick, Object.observe(已废弃), MutationObserver(html5新特性)

当执行栈中的所有同步任务执行完毕时,是先执行宏任务还是微任务呢?

  • 由于执行代码入口都是全局任务 script,而全局任务属于宏任务,所以当栈为空,同步任务任务执行完毕时,会先执行微任务队列里的任务。
  • 微任务队列里的任务全部执行完毕后,会读取宏任务队列中拍最前的任务。
  • 执行宏任务的过程中,遇到微任务,依次加入微任务队列。
  • 栈空后,再次读取微任务队列里的任务,依次类推。

 Detailed introduction to JavaScript operating mechanism (code example)

一句话概括上面的流程图:当某个宏任务队列的中的任务全部执行完以后,会查看是否有微任务队列。如果有,先执行微任务队列中的所有任务,如果没有,就查看是否有其他宏任务队列

接下来我们看两道例子来介绍上面流程:

Promise.resolve().then(()=>{
  console.log(&#39;Promise1&#39;)  
  setTimeout(()=>{
    console.log(&#39;setTimeout2&#39;)
  },0)
})
setTimeout(()=>{
  console.log(&#39;setTimeout1&#39;)
  Promise.resolve().then(()=>{
    console.log(&#39;Promise2&#39;)    
  })
},0)
复制代码

最后输出结果是Promise1,setTimeout1,Promise2,setTimeout2

  • 一开始执行栈的同步任务执行完毕,会去查看是否有微任务队列,上题中存在(有且只有一个),然后执行微任务队列中的所有任务输出Promise1,同时会生成一个宏任务 setTimeout2
  • 然后去查看宏任务队列,宏任务 setTimeout1 在 setTimeout2 之前,先执行宏任务 setTimeout1,输出 setTimeout1
  • 在执行宏任务setTimeout1时会生成微任务Promise2 ,放入微任务队列中,接着先去清空微任务队列中的所有任务,输出 Promise2
  • 清空完微任务队列中的所有任务后,就又会去宏任务队列取一个,这回执行的是 setTimeout2
console.log(&#39;----------------- start -----------------&#39;);
setTimeout(() => {
  console.log(&#39;setTimeout&#39;);
}, 0)
new Promise((resolve, reject) =>{
  for (var i = 0; i < 5; i++) {
    console.log(i);
  }
  resolve();  // 修改promise实例对象的状态为成功的状态
}).then(() => {
  console.log(&#39;promise实例成功回调执行&#39;);
})
console.log(&#39;----------------- end -----------------&#39;);

 Detailed introduction to JavaScript operating mechanism (code example)

七、题外话

如果要输出0~4,上面例题应该如何修改?

  1. 将var变为let
for (let i = 0; i < 5; i++) {
setTimeout(function() {  
  console.log(i);
  }, 1000);
}
复制代码
  1. 加个立即执行函数
for (var i = 0; i < 5; i++) {
    (function(i){
    setTimeout(function() {  
      console.log(i);
      }, 1000);
    })(i)
}
复制代码
  1. 也可以通过这样加闭包
for(var i = 1;i < 5;i++){  
      var a = function(){  
          var j = i;    
        setTimeout(function(){  
              console.log(j);  
          },1000)  
      }    
    a();
}

The above is the detailed content of Detailed introduction to JavaScript operating mechanism (code example). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete