小编给大家分享一下关于JavaScript执行机制的面试题,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
JavaScript的特点
1.JavaScript主要用来向HTML页面添加交互行为。2.JavaScript可以直接嵌入到HTML页面,但写成单独的js文件有利于结构和行为的分离。3.JavaScript具有跨平台特性,在绝大多数浏览器的支持下,可以在多种平台下运行。
同步和异步
同步任务进入主线程排队,异步任务进入事件队列中排队
同步任务和异步任务进入到不同的队列中,也就是上面讲的在不同地方排队。
同步任务进入主线程,异步任务进入事件队列,主线程任务执行完毕,事件队列中有等待执行的任务进入主线程执行,直到事件队列中任务全部执行完毕。
开胃菜
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并不是立刻执行,只是代表相比于其他定时器更早的进入主线程中执行。
加一盘
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。
宏任务 微任务
除了经常说的同步任务和异步任务之外,更可分为宏任务,微任务
主要宏任务:整段脚本scriptsetTimeoutsetTimeout...
主要微任务:promise.then...
执行流程:
整段脚本script作为宏任务开始执行
遇到微任务将其推入微任务队列,宏任务推入宏任务队列
宏任务执行完毕,检查有没有可执行的微任务
发现有可执行的微任务,将所有微任务执行完毕
开始新的宏任务,反复如此直到所有任务执行完毕
来一盘Promise
const p = new Promise(resolve => { console.log('a') resolve() console.log('b')})p.then(() => { console.log('c')})console.log('d')
结果:a b d c
整段script进入宏任务队列开始执行
promise创建立即执行,打印ab
遇到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创建立即执行,打印ab
遇到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将其推入宏任务队列中
定时器延迟时间相同,开始按照顺序执行宏任务,分别打印setTimeoutthen中的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
执行延迟为100的宏任务,打印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并不是立刻执行,只是代表相比于其他定时器更早的被执行
以宏任务和微任务进一步理解js执行机制
整段代码作为宏任务开始执行,执行过程中宏任务和微任务进入相应的队列中
整段代码执行结束,看微任务队列中是否有任务等待执行,如果有则执行所有的微任务,直到微任务队列中的任务执行完毕,如果没有则继续
执行新的宏任务执行新的宏任务,凡是在执行宏任务过程中遇到微任务都将其推入微任务队列中执行
反复如此直到所有任务全部执行完毕
看完了这篇文章,相信你对“关于JavaScript执行机制的面试题”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网行业资讯频道,感谢各位的阅读!