关于JavaScript运行机制的一些总结

栏目: JavaScript · 发布时间: 7年前

内容简介:说如果你看到这段代码,并知道正确的输出顺序。那说明你对这块掌握的差不多了。(直接翻到最后看结果)好,言归正传。

javascript 运行机制之前,先看一段代码:

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)
        })
    })
})

如果你看到这段代码,并知道正确的输出顺序。那说明你对这块掌握的差不多了。(直接翻到最后看结果)

好,言归正传。

在说是怎么运行的之前,先看几个概念。

执行上下文(Execution Context)

执行上下文简单来说就是一个执行环境。它有全局环境、函数环境和eval函数环境之分。它会在 javascript 引擎执行你的脚本的时候去创建。

执行栈(Execution Stack)

执行栈也就是常说的调用栈,它是一种拥有LIFO(后进先出)的数据结构。它会存储代码运行时创建的执行上下文

微任务(micro task)与宏任务(macro task)

javasript 中的任务分为微任务和宏任务两种,这两种任务的执行时机是不同的,因此区分js中哪些是宏任务,哪些是微任务则十分重要。我们常见的宏任务有: script任务setTimeoutajax 等,常见的微任务比较典型的是: Promise.resolve().then()process.nextTickMutationObserver 等。

事件循环(event loop)

js是单线程的,也就是说它一次仅能处理一个任务。但js所在的宿主环境,也就是我们所说的浏览器并不是单线程的(这里宿主环境仅讨论浏览器)。它在遇到一些任务时,比如说 setTimeoutevent listener 等。它会告诉浏览器:老兄帮个忙,事成后通知我一声,小弟我先干别的事去了。浏览器会回应说:交给我吧,小老弟,事成后我放到任务队列,自己去取啊。于是,js开始执行script任务,执行完了就开始检查有没有微任务啊,没有的话就从任务队列开始取宏任务执行,每执行完一次宏任务,就去看看有没有微任务,有的话就执行完成,再执行宏任务,如此往复。如下:

关于JavaScript运行机制的一些总结

了解了这几个概念,再来看看 javascript 是怎么执行代码的就比较轻松愉快了。开始吧

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)
        })
    })
})

js引擎在执行这段代码的时候,首先将全局执行上下文压入栈中:

关于JavaScript运行机制的一些总结

然后呢,在执行的时候会碰到 console.log 函数,将它压入栈中:

关于JavaScript运行机制的一些总结

这个时候,直接执行 console 函数,并输出 1 。然后 console 函数出栈:

关于JavaScript运行机制的一些总结

继续往下执行,碰到了 Promise.resolve().then() ,先将 Promise.resolve().then() 压入栈中(这里,我为了图方便就把它看成整体了,不然得画很多图)。

关于JavaScript运行机制的一些总结

然后执行 Promise.resolve().then() ,前面说过,这个 then() 函数是个微任务,它会将传入给它的回调函数加入到微任务队列中。

关于JavaScript运行机制的一些总结

然后 Promise.resolve().then() 就出栈了。

接着执行,遇到 promise 的构造函数,这个构造函数是一个宏任务,会直接将传递给它的函数压入栈中。

关于JavaScript运行机制的一些总结

执行 console 函数并输出 3 ,执行完, console 函数出栈,接着执行 resolve() 函数,并出栈。

然后继续执行 then 函数,将传递给 then 函数的参数函数放到微任务队列中:

关于JavaScript运行机制的一些总结

继续来,继续往下执行。碰到 console.log(6) ,二话不说,直接压入栈中,执行,输出 6 ,出栈,一气呵成。

接着,引擎碰到了 setTimeout 函数,这家伙是个宏任务,但同时它会将传递给它的函数,加入到任务队列中:

关于JavaScript运行机制的一些总结

好了,到此第一波宏任务就全部执行完毕。接着,引擎就会去看一下微任务队列中有没有任务,如果有的话,执行它们。

现在看到的是,微任务队列中有两个任务。按照队列的先入先出规则,先从 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)
}

加入到任务队列中去

关于JavaScript运行机制的一些总结

先执行:

function(){
Promise.resolve().then(function () {
        console.log(7)
        setTimeout(function () {
            console.log(8)
        })
    })
}

这里执行这个函数的时候遇到一个微任务,将这个微任务添加到微任务队列,如下:

关于JavaScript运行机制的一些总结

这批次的宏任务就执行完毕了,接着就回去检查微任务队列中有没有待执行的任务。一看还真有两个小可爱等待执行,于是没什么好说的,直接拧出去就执行

先是执行 console.log(7) ,然后输出 7 。接着执行 setTimeout ,将传递给他的任务添加到任务队列中去:

关于JavaScript运行机制的一些总结

最后就剩这两个函数了,按照队列的先入后出一次执行吧,输出 58

好了,最后的结果就是 1,3,6,2,4,7,5,8 。你写对了了吗?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

An Introduction to the Analysis of Algorithms

An Introduction to the Analysis of Algorithms

Robert Sedgewick、Philippe Flajolet / Addison-Wesley Professional / 1995-12-10 / CAD 67.99

This book is a thorough overview of the primary techniques and models used in the mathematical analysis of algorithms. The first half of the book draws upon classical mathematical material from discre......一起来看看 《An Introduction to the Analysis of Algorithms》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具