@@ -8,53 +8,64 @@ header-img: img/post-bg-ios9-web.jpg
8
8
catalog : true
9
9
tags :
10
10
- JavaScript
11
+ - Event Loop
11
12
---
12
13
13
- > 参考资料:
14
- - [ js引擎的执行过程(一)] ( https://heyingye.github.io/2018/03/19/js%E5%BC%95%E6%93%8E%E7%9A%84%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%EF%BC%88%E4%B8%80%EF%BC%89/ )
15
- - [[ 译] 理解 Javascript 执行上下文和执行栈] ( https://juejin.im/post/5bdfd3e151882516c6432c32 )
16
- - [ 这一次,彻底弄懂 JavaScript 执行机制] ( https://juejin.im/post/59e85eebf265da430d571f89 )
14
+ > 学习&参考资料:
15
+ > - [ 这一次,彻底弄懂 JavaScript 执行机制] ( https://juejin.im/post/59e85eebf265da430d571f89 )
16
+ > - [ 10分钟理解JS引擎的执行机制] ( https://segmentfault.com/a/1190000012806637 )
17
+ > - [ 微任务、宏任务与Event-Loop] ( https://segmentfault.com/a/1190000016022069 )
18
+ > - [ JavaScript 异步、栈、事件循环、任务队列] ( https://segmentfault.com/a/1190000011198232 )
17
19
18
- # JavaScript是什么鬼
20
+
21
+
22
+ ## 前言
19
23
写了2个月的前端,照葫芦画瓢可以写页面了,但是JavaScript是个什么鬼,怎么执行的,同事说es5,es6的执行过程有可能不同,what!我看的这些资料又是以哪个为标准......内心很崩溃,写此文搞清楚JavaScript引擎的执行过程。
20
24
21
- # JavaScript 的特点
25
+ ## JavaScript 的特点
22
26
* ** JavaScript是单线程语言**
23
27
在浏览器中一个页面永远只有一个线程在执行js脚本代码(在不主动开启新线程的情况下)
24
28
* ** JavaScript 是单线程语言,但是代码解析却十分的快速,不会发生解析阻塞。**
25
29
JavaScript是异步执行,通过** 事件循环(Event Loop)** 的方式实现。
26
30
27
- ## 为什么JavaScript是单线程的?
31
+ ** 为什么JavaScript是单线程的?**
28
32
js是为浏览器端设计的脚本语言,主要任务是操作Dom,如果设计成多线程,势必是需要牵扯多个线程争夺Dom资源,为了解决资源争夺问题必然要引入🔐,这样的实现会非常臃肿。
29
33
30
- ## 为什么需要异步?
34
+ ** 为什么需要异步?**
31
35
主要是用户友好,不让用户感觉到等待,如果浏览器处理一个任务时间很长,你能忍!?!设计成单线程,加上异步执行,就可以减少用户等待时间,俗称用户体验。
32
36
33
- ## 单线程如何实现异步?
37
+ ** 单线程如何实现异步?**
34
38
通过event loop实现异步,理解了event loop机制,就理解了JS的执行机制
35
39
36
- # 人脑运行代码检验理解js执行过程
37
- 这两个例子贴在这里,因为才看到这些例子的时候,懵逼,等待理解完后写出解答过程,看到此文的可以留言交流,因为我也不知道正确的分析过程是什么样的。
38
- ##题目(1)
39
- ```
40
- console.log(person);
41
- console.log(fun);
42
- var person="Eric";
43
- console.log(person);
44
-
45
- function fun() {
46
- console.log(person);
47
- var person="Tom";
48
- console.log(person);
49
- }
50
-
51
- fun();
52
- console.log(person)
53
- ```
54
40
41
+ ## JavaScript Event Loop(事件循环)
42
+ 上面说了,JavaScript单线程异步操作是通过Event Loop实现的,那么我们就需要了解Event Loop到底是个撒。
43
+
44
+ JavaScript是单线程的,当遇到需要超长时间才能执行完成的任务怎么办?为了解决单个任务执行时间超长的问题,JS根据当前任务是否可以立即执行完毕,将任务分为:
45
+ * 同步任务 (可以立即执行)
46
+ * 异步任务(不等待,先去做其他任务)
47
+
48
+ ``` js
49
+ console .log (1 );
50
+
51
+ setTimeout (function () {
52
+ console .log (2 )
53
+ }, 3000 );
55
54
56
- ##题目(2)
55
+ console . log ( 3 )
57
56
```
57
+ 按照同步任务、异步任务划分,以上代码的执行过程:1,3,2。
58
+
59
+ > - 代码加载进来,按照顺序执行,第一行代码 ` console.log(1) ` 同步任务,立即执行,打印 ` 1 `
60
+ > - 然后遇到` setTimeout() ` 函数,是异步任务,不等待,继续往后执行下面的代码
61
+ > - 遇到 ` console.log(3) ` 同步任务,立即执行,打印 ` 3 `
62
+ > - 回到异步任务 ` setTimeout() ` 函数, 打印 ` 2 `
63
+
64
+ ![ image.png] ( https://upload-images.jianshu.io/upload_images/5013098-97056b990bea0bfb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
65
+
66
+
67
+ 项目中的代码哪有这么简单,一般项目中的代码复杂度都是下面这样的
68
+ ``` js
58
69
setTimeout (function (){
59
70
console .log (' 定时器开始啦' )
60
71
});
@@ -69,37 +80,103 @@ new Promise(function(resolve){
69
80
});
70
81
71
82
console .log (' 代码执行结束' );
83
+ ```
72
84
85
+ 那么按照之前的同步和异步任务划分,代码运行的结果应该是:
86
+ ``` js
87
+ 懵逼了。。。。
88
+ ... 怎么判断是同步任务还是异步任务?
89
+ ... 同步任务执行完后,剩下的异步任务是什么顺序调用呢?
73
90
```
91
+ ###### 怎么判断是同步任务还是异步任务?
92
+ 一般来说满足一定条件后,才去执行的,这类代码,我们叫异步代码,被视作异步任务。有一些常见的异步操作有:` setTimeout() ` ,` Promise的then, catch 等callback 函数 ` ...
93
+ 当你写的代码越多,对编程理解的不断深入,就会很清晰的知道哪些是异步任务。
74
94
95
+ ###### 那么,多个异步任务的调用顺序是怎么样的?
96
+ 我们先假设异步任务的调用顺序是按照添加到任务队列的先后顺序执行的。
97
+ 当我们知道 ` setTimeout() ` ,` Promise的 then 函数 ` 是异步任务的时候,我们按照现有的同步和异步任务处理过程,模拟出代码的执行结果是:
98
+ > - ` setTimeout ` 是异步任务,先放一放,不执行
99
+ > - ` Promise 的 then 函数 ` 是异步任务,先放一放,不执行,只执行` 马上执行for循环啦 `
100
+ 此时,按照假设,` Promise 的 then 函数 ` 任务放在` setTimeout ` 任务后面。
101
+ > - 打印` 代码执行结束 ` , 此时,同步任务执行完毕,按顺序执行异步任务
102
+ > - ` 定时器开始啦 `
103
+ > - ` 执行then函数啦 `
75
104
105
+ 但是,将代码放在chrome上运行的时候,真正的结果不是按照之前的假设执行的,而是先执行的 ` Promise 的 then 函数 ` , 然后执行的` setTimeout ` 。
106
+ 此时,我们可以认为异步任务按照添加顺序执行的假设不成立。
107
+ ![ image.png] ( https://upload-images.jianshu.io/upload_images/5013098-a2c0994960efba0b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
108
+ 知识的匮乏,会让我们在接触到新问题时忘记问一下为什么。
109
+ - 为什么js的异步任务不是按照添加的顺序执行?
110
+ - 为什么js的Event Loop 会设计出两个新概念:** 宏任务&微任务** 来控制任务的执行过程?
76
111
77
- ##分析过程
78
- ### 题目(1)分析过程
79
- ![ 题目(1)运行结果.png] ( https://upload-images.jianshu.io/upload_images/5013098-f9d4cee12e8bc6e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
80
- ### 题目(2)分析过程
81
- ![ 题目(2)运行结果.png] ( https://upload-images.jianshu.io/upload_images/5013098-07584fb92bb8ca25.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
112
+ 理解完了宏任务和微任务的原理,也没有想明白,上面这两个为什么?需再思考思考。
82
113
114
+ ### 宏任务&微任务
115
+ 可以阅读 [ 微任务、宏任务与Event-Loop] ( https://segmentfault.com/a/1190000016022069 ) 的这篇文章来理解宏任务和微任务的概念。
83
116
84
- # JavaScript Event Loop(事件循环)
85
- 上面说了,JavaScript单线程异步操作是通过Event Loop实现的,那么我们就需要了解Event Loop到底是个撒。
117
+ ** 自己的理解**
118
+ - 宏任务是<script > 标签代码里的所有任务已经按照哪些是宏任务已经排好队列了。
119
+ - 微任务是当前宏任务中产生的异步任务,等待异步任务执行完后进入微任务队列。
86
120
87
- JavaScript是单线程的,那么当遇到需要超长时间才能执行完成的任务怎么办?那么根据任务是否可以立即执行完毕,将任务分为:
88
- * 同步任务 (可以立即执行)
89
- * 异步任务(不等待,知道任务执行时间长,先去做其他任务)
121
+ 当JavaScript代码开始执行的时候,此时,只有一个宏任务,就是<script >代码里面的所有同步任务,这些同步任务里面会有一些带有callback函数的异步调用,产生了微任务,此时,会将已经返回的callback 函数放到微任务队列。
122
+
123
+ 在当前宏任务中产生的微任务没有执行完成时,是不会执行下一个宏任务的。也就是说微任务队列只有一个,只有当微任务队列为空的时候,才会执行下一个宏任务。
124
+
125
+ 这[ 微任务、宏任务与Event-Loop] ( https://segmentfault.com/a/1190000016022069 ) 这篇文章中,给出了业界比较流行的宏任务和微任务的分类,并且和node进行了对比:
126
+ ![ 宏任务和微任务.png] ( https://upload-images.jianshu.io/upload_images/5013098-49a2a18b32e5ffce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
90
127
91
128
129
+ 下面这张图来自 [ JavaScript 异步、栈、事件循环、任务队列] ( https://segmentfault.com/a/1190000011198232 ) ,这篇文章图文并茂,能够更好的理解JavaScript引擎执行过程。
130
+ ![ JavaScript异步,Event Loop,任务队列.png] ( https://upload-images.jianshu.io/upload_images/5013098-4d40f5db1e0b09ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
92
131
93
- # 原理解析JavaScript引擎执行过程
94
- JavaScript引擎执行过程分为三个阶段:
95
- 1 . 语法分析
96
- 2 . 预编译阶段
97
- 3 . 执行阶段
132
+ 从图上可以看出,任务队列分为宏任务队列和微任务队列。宏任务队列可以有多个,但是微任务队列只能有一个。
133
+
134
+ #### 代码解析
135
+ ``` js
136
+ setTimeout (function (){
137
+ console .log (' 定时器开始啦' )
138
+ });
139
+
140
+ new Promise (function (resolve ){
141
+ console .log (' 马上执行for循环啦' );
142
+ for (var i = 0 ; i < 10000 ; i++ ){
143
+ i == 99 && resolve ();
144
+ }
145
+ }).then (function (){
146
+ console .log (' 执行then函数啦' )
147
+ });
148
+
149
+ console .log (' 代码执行结束' );
150
+ ```
151
+
152
+ 这段代码解析后,会立即从头到尾执行,这是第一个宏任务,此时是没有微任务的。
153
+ - 遇到` setTimeout() ` , 判断是宏任务,放到宏任务队列
154
+ - 继续执行,遇到 ` Promise() ` ,那么会打印` 马上执行for循环啦 ` , ` then() ` 函数是异步执行,此时产生了微任务,等待当前的宏任务执行完毕后,才会执行微任务
155
+ - 打印` 代码执行结束 `
156
+ - 当前宏任务执行完毕,查看微任务是否存在,发现了 ` then() ` 函数这个微任务需要执行,打印` 执行then函数啦 `
157
+ - 当前宏任务和它产生的微任务已经执行完毕,可以执行下一个宏任务,发现了 ` setTimeout() ` ,打印` 定时器开始啦 `
158
+
159
+
160
+ ## 理解Event Loop
161
+ ** 2019年02月14日,此时的理解**
162
+ ``` js
163
+ 当JavaScript代码准备被执行的时候,只有宏任务,即代码里的所有能够立即执行的同步任务,
164
+ 当同步任务中产生的一些异步任务准备完毕后,会将这些异步任务放到微任务队列,
165
+ 同时,同步任务中会有其他的一些宏任务,那么这些任务不会立即执行,
166
+ 而是会放到宏任务队列,等待当前宏任务执行完毕,
167
+ 随后去执行产生的微任务,才会去执行下一个宏任务。
168
+ ```
169
+ 期待以后温故知新,理解更深入。
98
170
99
- 在HTML中写JavaScript脚本的时候,需要添加<script >标签,浏览器首先按顺序加载由<script >标签分割的js代码块,加载js代码块完毕后,立刻进入以上三个阶段,然后再按顺序查找下一个代码块,再继续执行以上三个阶段,无论是外部脚本文件(不异步加载)还是内部脚本代码块,都是一样的原理,并且都在同一个全局作用域中。
171
+ ## Conclusion
172
+ 现在信息越来越多,当你需要一些深入的理解时候,去找到一些文章的时候,发现很多文章都很相像,以至于不清楚的地方,翻看了很多相似的文章还是不清不楚。需要不断反思,不断查找,才能完善自己的知识体系。
100
173
101
- ## 语法分析
174
+ ## Punch List
175
+ - [ JavaScript引擎、虚拟机、运行时环境是一回事儿吗?] ( https://www.zhihu.com/question/39499036 )
176
+ - [ 浏览器与Node的事件循环(Event Loop)有何区别?] ( https://juejin.im/post/5c337ae06fb9a049bc4cd218 )
102
177
103
- js脚本加载完毕后,会首先进行语法分析阶段,该阶段主要作用是:
104
- > 分析js脚本代码块的语法是否正确,如果出现不正确,则向外抛出一个语法错误(),停止该js代码块的执行,然后继续查找下一个并加载下一个代码块,如果语法正确,则会进行预编译阶段。
105
- (疑问:出现语法错误,)
178
+ > 学习过程中,阅读的相关资料
179
+ > - [ js引擎的执行过程(一)] ( https://heyingye.github.io/2018/03/19/js%E5%BC%95%E6%93%8E%E7%9A%84%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%EF%BC%88%E4%B8%80%EF%BC%89/ )
180
+ > - [[ 译] 理解 Javascript 执行上下文和执行栈] ( https://juejin.im/post/5bdfd3e151882516c6432c32 )
181
+ > - [ JavaScript运行原理解析] ( https://www.kancloud.cn/digest/liao-js/149467 )
182
+ > - [ Javascript 工作原理] ( https://cnodejs.org/topic/579e341885dba6b12ac58583 )
0 commit comments