几道常见面试题来看
JavaScript
执行机制
根据 JavaScript
的运行环境,锁定它为单线程,任务须要排队执行,若是网站资源比较大,这样会致使浏览器加载会很慢,但实际上并无,你们确定马上想到了同步和异步。面试
所谓的同步和异步也是在排队,只是排队的地方不一样。promise
同步任务进入主线程排队,异步任务进入事件队列中排队
同步任务和异步任务进入到不一样的队列中,也就是上面讲的在不一样地方排队。浏览器
同步任务进入主线程,异步任务进入事件队列,主线程任务执行完毕,事件队列中有等待执行的任务进入主线程执行,直到事件队列中任务所有执行完毕。异步
console.log('a') setTimeout(function(){ console.log('b') }, 200) setTimeout(function(){ console.log('c') }, 0) console.log('d')
结果:a d c b
测试
从上到下,该进入主线程的进入主线程,该进入事件队列的进入事件队列。网站
那么主线程中存在 console.log('a')
和 console.log('d')
,定时器 setTimeout
延迟一段时间执行,顾名思义异步任务进入事件队列中,等待主线程任务执行完毕,再进入主线程执行。线程
定时器的延迟时间为 0
并非马上执行,只是表明相比于其余定时器更早的进入主线程中执行。code
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i) }, 1000) }
结果:十个10
队列
每次 for
循环遇到 setTimeout
将其放入事件队列中等待执行,直到所有循环结束,i
做为全局变量当循环结束后 i = 10
,再来执行 setTimeout
时 i
的值已经为 10
, 结果为十个10。事件
将 var
改成 let
,变量做用域不一样,let
做用在当前循环中,因此进入事件队列的定时器每次的 i
不一样,最后打印结果会是 0 1 2...9。
除了常常说的同步任务和异步任务以外,更可分为宏任务,微任务
主要宏任务:整段脚本script
setTimeout
setTimeout
...
主要微任务:promise.then
...
执行流程:
const p = new Promise(resolve => { console.log('a') resolve() console.log('b') }) p.then(() => { console.log('c') }) console.log('d')
结果:a b d c
promise
建立当即执行,打印 a
b
,promise.then
进入微任务队列,console.log('d')
打印 d
,c
。setTimeout(function(){ console.log('setTimeout') }, 0) const p = new Promise(resolve => { console.log('a') resolve() console.log('b') }) p.then(() => { console.log('c') }) console.log('d')
结果:a b d c setTimeout
setTimeout
进入宏任务队列,promise
建立当即执行,打印 a
b
,promise.then
进入微任务队列,console.log('d')
打印 d
,c
,setTimeout
开始执行,打印 setTimeout
setTimeout(function(){ console.log('setTimeout') }, 0) const p = new Promise(resolve => { console.log('a') resolve() console.log('b') }) p.then(() => { console.log('c') setTimeout(function(){ console.log('then中的setTimeout') }, 0) }) console.log('d')
结果:a b d c setTimeout then中的setTimeout
c
,遇到 setTimeout
将其推入宏任务队列中setTimeout
then中的setTimeout
console.log('a'); new Promise(resolve => { console.log('b') resolve() }).then(() => { console.log('c') setTimeout(() => { console.log('d') }, 0) }) setTimeout(() => { console.log('e') new Promise(resolve => { console.log('f') resolve() }).then(() => { console.log('g') }) }, 100) setTimeout(() => { console.log('h') new Promise(resolve => { resolve() }).then(() => { console.log('i') }) console.log('j') }, 0)
结果:a b c h j i d e f g
a
promise
当即执行,打印 b
promise.then
推入微任务队列setTimeout
推入宏任务队列c
,遇到 setTimeout
推入宏任务队列排队等待执行h j
,promise.then
推入微任务队列i
,继续执行宏任务,打印 d
e f
,执行微任务打印 g
,全部任务执行完毕console.log('start') a().then(() => { console.log('a_then') }) console.log('end') function a() { console.log('a_function') return b().then((res) => { console.log('res', res) console.log('b_then') return Promise.resolve('a方法的返回值') }) } function b() { console.log('b_function') return Promise.resolve('返回值') }
结果:start
a_function
b_function
end
res 返回值
b_then
a_then
根据上面例子的流程讲解来思考这个,加深理解
JavaScript
单线程,任务须要排队执行0
并非马上执行,只是表明相比于其余定时器更早的被执行