1、js的运行环境
js是一门单线程语言。因为js是脚本语言(解释运行而非编译),运行时必须要借助引擎来运行,所以它可以在封装了引擎的环境下运行,而当js运行时,他会有不同的运行环境。
运行环境主要有:
Global Code~js代码开始的默认运行环境;Function Code:代码执行在js函数中;Eval Code: 使用eval()执行代码。
2、js的运行过程
分为预编译期和执行期
预编译期:
a、浏览器的js引擎“解析”js代码;
b、建立arguments对象,函数,参数,变量;
c、建立作用域链;
d、确定this指向。
执行期:
按照从上到下的顺序执行代码
3、执行上下文
执行上下文它是一个对象,由js的执行引擎创建,具有三个属性:变量对象、作用域链、this指向。
4、javascript事件循环
广义的来区分,任务可以区分为同步任务和异步任务。
导图要表达的内容用文字来表述的话如下:
a、同步和异步任务分别进入不同的执行场所,同步的进入主线程,异步的进入event talbe并注册函数。
b、当指定的事情完成时,event table会将这个函数移入event queue。
c、主线程内的任务执行完毕为空,会去event queue读取对应的函数,进入主线程执行。
d、上述过程会不断重复,也就是常说的event loop 事件循环。
注意:js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去event queue那里检查是否有等待被调用的函数。
除了广义的同步任务和异步任务,我们对任务有更精细的定义:
macro-task(宏任务):包括整体代码script、setTimeout、setInterval、setImmediate,requestAnimationFrame,I/O,UI渲染等
micro-task(微任务):Promise、process.nextTick、MutationObserve,queueMicrotask
不同类型的任务会进入对应的Event Queue,事件循环的顺序,决定js代码的执行顺序。进入整体代码后,开始第一次循环,接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
可以试着做一下下面这个例子练手:
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
执行的结果:1,7,6,8,2,4,3,5,9,11,10,12。
接下来我们详细分析一下这个例子:
1、首先开始执行宏任务,输出 1 ;遇到setTimeout直接放入宏任务;process直接放入微任务 promise执行输出7,并将then放入到微任务;遇到setTimeout直接放入宏任务; 输出:1、7
2、宏任务已经执行了一轮,开始执行微任务,输出process的6,then的8;输出:6、8
3、开始第二轮宏任务:第一个setTimeout首先输出2,然后是promise的4,宏任务已经没有,接着开始执行微任务,输出3、5;输出:2、4、3、5
4、开始第3轮宏任务:第二个setTimeout首先输出9,然后是promise的11,宏任务已经没有,接着开始执行微任务,输出10,12;输出:9、11、10、12
补充:
a、在当前的微任务没有执行完成时,是不会执行下一个宏任务的。
b、所有会进入的异步都是指的事件回调中的那部分代码:也就是说new promise 在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行的。
后记:
事件循环是js实现异步的一种方法,也是js的执行机制。