学习笔记:JS引擎的执行机制

前言:昨天在看到几道关于延时执行的题目,当时看到结果一脸懵逼,于是去好好的了解了下JS引擎的执行机制,在这里做个笔记。

一、前置知识——同步与异步的概念、区分及执行机制

JS最初是被设计在浏览器中使用的,为了避免多个进程同时对一个Dom操作导致冲突,因此将它设计成了单线程语言。

但是JS是能够实现异步操作的,假设JS中不存在异步,代码都自上而下顺序执行,那么如果上一行代码解析时间很长的话,下面的代码就会被阻塞不执行,严重影响用户体验,而实现异步操作主要通过事件循环(event loop)操作。看以下例子:

console.log(1)

setTimeout(function(){

       console.log(2)

 },0)

console.log(3)          //最终打印顺序为1 3 2

如果不了解JS同步和异步任务执行的机制的话,会在这里出现一个疑惑:虽然console.log(2)放在一个延时执行语句里,但延时执行的时间为0,究竟是2先打印还是3先打印?

为了分析上述代码是如何执行的,我们首先必须要了解同步与异步的概念,并能够区分它们。

同步代码不管之前代码输出的结果是什么,只要程序运行到这个语句了都会执行,如上面的console.log(2)和console.log(3),同步代码并没有执行的先决条件。而异步则不同,它需要满足一定的条件后才执行代码,可以是等待一段时间、等待一个事件发生等等,如上面的setTimeout,即使等待时间为0,它也属于异步操作。

同步与异步操作可以按以下规则进行划分:

1、定时器都是异步操作

2、事件绑定都是异步操作

3、AJAX中一般我们都采取异步操作(也可以同步)

4、回调函数可以理解为异步(不是严谨的异步操作)

剩下的都是同步处理

其次,要知道JS执行代码的机制

1、首先判断代码是同步还是异步,同步则进入主线程,异步就进入event table(事件表)

2、异步任务在event table中注册函数,当满足执行条件后,被推入event queue(事件队列)

3、同步任务进入主线程后一直顺序执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主进程中执行

利用上述的知识来分析一下前面的代码

console.log(1)                  //console.log(1)是同步任务,放入主线程中

setTimeout(function(){      //setTimeout()是异步任务放入event table中,0s后将里面的函数推入event queue

       console.log(2)       

},0)

console.log(3)                   //console.log(3)是同步任务,放入主线程中

当主线程运行完打印1、3的任务后,会去event queue查看是否有可执行的语句,从而执行setTimeout里面的函数


二、宏任务与微任务

当了解完上面的知识点之后觉得自己已经掌握JS运行代码的机制,然后当看到下面这个代码的运行结果时一脸懵逼

按照前面的思路进行分析执行顺序应该是这样

1、setTimeout()是异步任务,放入event table,0秒后里面的函数被推入event queue

2、new promise是同步任务,直接进入主线程执行console.log("马上执行for循环啦")及for循环

3、.then是异步任务,放入event table,promise的函数执行完后.then里面的函数被推入event queue

4、console.log("代码执行结束")是同步任务,直接进入主线程执行

5、主线程任务运行完毕后,查看event queue,里面有2个可执行的任务,按任务被推入队列的顺序执行代码,先执行setTimeout()再执行.then

按照这个思路打印结果应该为:马上执行for循环啦--代码执行结束--定时器开始啦--执行then函数

但实际上这段代码的运行结果为:马上执行for循环啦--代码执行结束--执行then函数--定时器开始啦

。。。。。

首先,前面关于同步和异步代码执行的机制并没有错,但在JS执行机制中,还有另一种机制的划分:宏任务(macro-task)和微任务(micro-task)

1、宏任务:包括整体代码script、setTimeout、setInterval

2、微任务:包括promise、process.nextTick

宏任务与微任务的执行机制如下:

1、首先执行宏任务,过程中如果遇到微任务,将其放入微任务的event queue

2、当前宏任务执行完后,查看微任务的event queue,依次执行里面的任务

3、该轮微任务执行完毕后,下一轮event loop查看宏任务的event queue是否有任务并执行


结合同步、异步、宏任务、微任务的机制来分析上面给出的代码

1、先执行script里的宏任务,遇到setTimeout()异步任务,0秒后将其放入宏任务的event queue中

2、遇到new promise同步任务,立即执行,打印"马上执行for循环啦"

3、遇到.then异步任务,将其放入微任务的event queue中

4、遇到console.log()同步任务,立即执行,打印"代码执行结束"

5、至此,本轮script下的宏任务执行完毕,查看本轮的微任务,发现有一个.then任务,执行里面的函数,打印"执行then函数啦"

6、到这里,本轮的宏任务及微任务都执行完了,本轮event loop结束

7、下一轮event loop开始,在宏任务的event queue里发现有一个setTimeout()任务,执行里面的函数,打印"定时器开始啦"

所以最后结果为:马上执行for循环啦--代码执行结束--执行then函数啦--定时器开始啦


三、关于setTimeout

看了上面的例子,就会发现,setTimeout实际上并不是按照我们给定的延时时间来执行的,例如 

setTimeout(function(){

       console.log("执行延时函数啦")

},5000)

以上代码并不意味着5s后执行setTimeout里面的函数,而是代表5s后setTimeout里的函数会被推入event queue中,当主线程空闲时,才会去执行这段代码,如果主线程任务执行了10s,那这个函数就只能10s后再执行了

所以执行setTimeout里面的代码需满足2个条件:(1)设定时间到达;(2)主线程空闲;当2个条件都满足代码才会被执行

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容