网上看了好多js执行机制的帖子,自己也做了很多尝试,为了以后工作需要,今天整理一篇出来,理解不到位的请多多指正。
1.js是单线程语言,只能同时做一件事情,js和DOM共用一个线程(js可以修改DOM),DOM渲染中js必须停止,js进行过程中DOM渲染必须停止。
问题1
如果一个大型网站,需要在首页请求很多图片来装饰,按照js单线程的原理,是不是就得等到所有图片都请求成功后才能加载出网页?事实并非如此,那么这其中的解决方法是什么呢?
问题2
// 1
setTimeout(() => {
console.log('执行1')
}, 3000)
// 2
new Promise((resolve) => {
console.log('执行2')
for (var i = 0; i < 10000; i++) {
i == 99 && resolve()
}
}).then(() => {
// 3
console.log('执行3')
})
// 4
console.log('执行4')
理想打印顺序
- 执行1
- 执行2
- 执行3
- 执行4
实际打印顺序
- 执行2
- 执行4
- 执行3
- 执行1
解释上面两个问题,就必须弄清楚js的执行机制,同时需要了解异步任务和同步任务
因为js是单线程,异步才应运而生!
当我们打开网站时,网页的渲染过程就是一大堆同步任务,比如页面骨架和页面元素的渲染。而像加载图片之类占用资源大耗时久的任务,就是异步任务。关于这部分有严格的文字定义,但本文的目的是用最小的学习成本彻底弄懂执行机制,所以我们用导图来说明:
上图用文字描述的话:
- 同步和异步任务分别进入不同的执行”场所”,同步的进入主线程,异步的进入Event Table并注册函数。
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue
- 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行
- 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
上述就可以解释通第一个问题了
上图用文字描述的话:
- 异步任务分为宏任务、微任务
- 遇到setTimeout,其回调函数被分发到宏任务Event Queue中
- 遇到Promise,new Promise直接执行,then被分发到微任务Event Queue中。
- 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
1.Event Loop是JavaScript的执行机制
2.执行和运行有很大的区别,JavaScript在不同的环境下,比如node,浏览器,Ringo等等,执行方式是不同的。而运行大多指JavaScript解析引擎,是统一的。
写在最后
我从来不认为半小时是微不足道的一段时间。
——达尔文