console.log(1)
setTimeout(function(){
console.log(2)
},0)
console.log(3)
问:这道题打印顺序?
1 → 3 → 2
一、JS是单线程
- JS是单线程的,同一时间只能做一件事,运行栈只执行一个任务
二、任务队列
- 任务队列:同步任务在前面,异步任务在后面
- 异步任务分类:分为宏任务与微任务, 微任务优先级高于宏任务
- 微任务:process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)
- 宏任务:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
- 定时器模块:执行完定时器后放入宏任务,等待主线程执行,主线程执行完的时候,定时器模块就已经开始计时了;
- 多个定时器:根据定时器的秒数触发,秒数越小,越先触发; 秒数相同,前面的先触发
console.log('A')
while (true) {}
console.log('B')
只会输入A, 然后死循环
console.log('A')
setTimeout(function () {
console.log('B')
}, 0)
while(1) {}
只会输入A, 然后死循环,因为任务队列需要等同步代码执行完,才会执行
for (var i =0; i< 4; i++) {
setTimeout(function () {
console.log(i)
}, 1000)
}
问:会运行几次,输出结果是什么?
会运行四次,每次输出结果是4
- 循环是同步代码,setTimeout是异步代码
- 异步队列放入时间:等待1000毫秒时间到了,会把异步代码放入任务队列
- 等同步代码执行完再执行任务队列
event loop 指的是运作栈中执行完一个任务后,从任务队列取出一个任务放入运行栈中继续执行,直到所有任务队列的任务执行完成这个过程叫做 event loop
三、面试题解析
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i); // 3 3 3
}, 1000);
}
// i = 0 , 遇到定时器1,挂起, i++
// i = 1, 遇到定时器2, 挂起, i++
// i = 2, 遇到定时器3, 挂起, i++
// i = 3 循环结束, 执行定时器1 , console.log(i) ,输出 3
// i = 3 循环结束, 执行定时器2 , console.log(i) ,输出 3
// i = 3 循环结束, 执行定时器2 , console.log(i) ,输出 3
let name;
setTimeout(() => {
name = '梁峻荣';
console.log(name); // 梁峻荣
}, 1000);
if (name) {
name = 'jsliang';
console.log(name);
}
// name = undefind , 遇到定时器, 挂起
// name = undefind , 不满足,跳过
// 同步任务结束后,1秒后,执行 name ='梁峻荣' ,打印 "梁峻荣"
for (var i = 0; i < 3; i++) {
}
for (let j = 0; j < 3; j++) {
}
console.log(i);
console.log(j);
参考书籍:
JavaScript异步编程:设计快速响应的网络应用
for (var i = 0; i <= 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
// 打印 4, 4次
需要知道三件事
- 这里只有一个名为i的变量,