This article brings you a summary of the JavaScript operating mechanism (code examples), which has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
Before talking about the javascript operating mechanism, let’s look at a piece of code:
console.log(1) Promise.resolve().then(function () { console.log(2) }) new Promise(function(resolve, reject){ console.log(3) resolve() }).then(function () { console.log(4) setTimeout(function () { console.log(5) }) }) console.log(6) setTimeout(function () { Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) })
If you see this code and know the correct output sequence. That means you have almost mastered this area. (Go directly to the end to see the results)
Okay, let’s get down to business.
Before talking about how it works, let’s look at a few concepts.
Execution Context (Execution Context)
Execution context is simply an execution environment. It has global environment, function environment and eval function environment. It will be created when the JavaScript engine executes your script.
Execution Stack
The execution stack is also commonly known as the call stack. It is a data structure with LIFO (last in first out). It stores the execution context created when the code is running.
Micro task (micro task) and macro task (macro task)
The tasks in javasript are divided into micro tasks and macro tasks There are two types of tasks. The execution timing of these two tasks is different, so it is very important to distinguish which are macro tasks and which are micro tasks in js. Our common macro tasks include: script tasks, setTimeout, ajax, etc. Common micro tasks are more typical: Promise.resolve().then(), process.nextTick, MutationObserver, etc.
Event loop (event loop)
js is single-threaded, which means that it can only handle one task at a time. But the host environment where js is located, which is what we call the browser, is not single-threaded (the host environment only discusses the browser here). When it encounters some tasks, such as setTimeout, event listener, etc. It will tell the browser: Brother, do me a favor and let me know when it's done. I'll go do other things first. The browser will respond: Leave it to me, little brother. When it is done, I will put it in the task queue and pick it up myself. So, js starts to execute the script task, and after the execution is completed, it starts to check whether there are microtasks. If not, it starts to fetch the macrotask from the task queue for execution. After each macrotask is executed, it checks to see if there are any microtasks. If so, Once the execution is complete, execute the macro task again, and so on. As follows:
After understanding these concepts, it will be easier and more enjoyable to look at how javascript executes the code. Let’s get started
console.log(1) Promise.resolve().then(function () { console.log(2) }) new Promise(function(resolve, reject){ console.log(3) resolve() }).then(function () { console.log(4) setTimeout(function () { console.log(5) }) }) console.log(6) setTimeout(function () { Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) })
When the js engine executes this code, it first pushes the global execution context into the stack:
Then, during execution, you will encounter the console.log function and push it onto the stack:
At this time, execute the console function directly , and output 1. Then the console function pops out of the stack:
Continues execution and encounters Promise.resolve().then(). First, Promise.resolve( ).then() is pushed onto the stack (here, I regard it as a whole for the convenience of drawing, otherwise I would have to draw a lot of pictures).
Then execute Promise.resolve().then(). As mentioned before, this then() function is a microtask, and it will pass the callback function passed to it. Join the microtask queue.
Then Promise.resolve().then() pops off the stack.
Then execute and encounter the constructor of promise. This constructor is a macro task and will directly push the function passed to it onto the stack.
Execute the console function and output 3. After execution, the console function is popped from the stack, and then the resolve() function is executed and popped from the stack.
Then continue to execute the then function and put the parameter function passed to the then function into the microtask queue:
Continue to come, continue to Execute below. When encountering console.log(6), without saying a word, it is directly pushed into the stack, executed, outputs 6, and popped out of the stack, all in one go.
接着,引擎碰到了setTimeout函数,这家伙是个宏任务,但同时它会将传递给它的函数,加入到任务队列中:
好了,到此第一波宏任务就全部执行完毕。接着,引擎就会去看一下微任务队列中有没有任务,如果有的话,执行它们。
现在看到的是,微任务队列中有两个任务。按照队列的先入先出规则,先从function () {console.log(2)}开始执行。先是函数入栈,然后执行函数,输出2,然后函数出栈。
接着执行下面这段代码:
console.log(4) setTimeout(function () { console.log(5) })
先从console.log(4)开始,先将它入栈,然后执行它,输出4,然后函数出栈。
接着执行:
setTimeout(function () { console.log(5) })
将
function () { console.log(5) }
加入到任务队列中去
先执行:
function(){ Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) }
这里执行这个函数的时候遇到一个微任务,将这个微任务添加到微任务队列,如下:
这批次的宏任务就执行完毕了,接着就回去检查微任务队列中有没有待执行的任务。一看还真有两个小可爱等待执行,于是没什么好说的,直接拧出去就执行
先是执行console.log(7),然后输出7。接着执行setTimeout,将传递给他的任务添加到任务队列中去:
最后就剩这两个函数了,按照队列的先入后出一次执行吧,输出5和8。
好了,最后的结果就是1,3,6,2,4,7,5,8。你写对了了吗?
The above is the detailed content of Summary of JavaScript operating mechanism (code example). For more information, please follow other related articles on the PHP Chinese website!