JavaScript 执行机制原理

JavaScript 运行机制原理

JavaScript 是单线程、异步、非阻塞、解释型脚本语言。”

JavaScript 运行机制

同步任务(synchronous)

异步任务(asynchronous)

在所有同步任务执行完之前,任何的异步任务是不会执行的

那么有哪些会进入异步任务队列?

setTimeoutsetlnterval
JavaScript DOM事件
ES6中的Promise
Ajax异步请求

微任务(Microtask)与宏任务(Macrotask)

异步任务又分为:微任务(Microtask)和宏任务(Macrotask)
宏任务队列可以有多个,微任务队列只有一个

JavaScript异步任务中那些是微任务?那些是宏任务?

微任务包括: new Promise().then(回调), process.nextTick, Object.observe(已废弃), MutationObserver(html5新特性)
宏任务包括:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering

理解Event Loop

单线程如何实现异步?

通过Event loop(事件循环)实现,从Event loopJavaScript运行机制

请看下面例子:

1
2
3
4
5
6
7
var arr = [1, 2, 3, 4, 5, 6, 7];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(i);
});
};
// 打印出来的结果是7个7

思考一下最后结果会输出什么?

答案:7个7

为什么不是按照我们预期的结果来输出?

setTimeout()是个异步定时函数,JavaScript是单线程,所以就算延时为0,它也是要等到for循环语句执行完了,才到它执行,每执行一次for语句就会就会产生一个异步执行,放在等待队列里,所以最后执行时就是输出7个7了

将上面的代码再进行改造一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 方法一
var arr = [1, 2, 3, 4, 5, 6, 7];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(i);
});
};
// 0, 1, 2, 3, 4, 5, 6

// 方法二
var arr = [1, 2, 3, 4, 5, 6, 7];
for (var i = 0; i < arr.length; i++) {
setTimeout(function(i) {
console.log(i);
}(i));
};
// 0, 1, 2, 3, 4, 5, 6

参考文章

Understanding JS: The Event Loop
The JavaScript Event Loop: Explained
JavaScript 运行机制详解:深入理解Event Loop
阮一峰 - 什么是 Event Loop?
阮一峰 - JavaScript 运行机制详解:再谈Event Loop
稀土掘金 - 一次性搞懂JavaScript 执行机制
稀土掘金 - 这一次,彻底弄懂 JavaScript 执行机制
稀土掘金 - 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理
稀土掘金 - 微任务、宏任务与Event-Loop
Mozilla Developer Networks - Worker
详解JavaScript中的Event Loop(事件循环)机制
深入浅出JavaScript运行机制