用几道面试题来看JavaScript执行机制


Posted in Javascript onApril 30, 2021

前面的话

根据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...

执行流程:

1.整段脚本script作为宏任务开始执行

2.遇到微任务将其推入微任务队列,宏任务推入宏任务队列

3.宏任务执行完毕,检查有没有可执行的微任务

4.发现有可执行的微任务,将所有微任务执行完毕

5.开始新的宏任务,反复如此直到所有任务执行完毕

来一盘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

1.整段script进入宏任务队列开始执行

2.promise创建立即执行,打印ab

3.遇到promise.then进入微任务队列

4.遇到console.log('d')打印d

5.整段代码作为宏任务执行完毕,有可执行的微任务,开始执行微任务,打印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

1.setTimeout进入宏任务队列

2.promise创建立即执行,打印ab

3.遇到promise.then进入微任务队列

4.遇到console.log('d')打印d

5.有可执行的微任务,打印c

6.微任务执行完毕,开始执行新的宏任务,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

1.同上

2.执行微任务打印c,遇到setTimeout将其推入宏任务队列中

3.定时器延迟时间相同,开始按照顺序执行宏任务,分别打印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

1.打印a

2.promise立即执行,打印b

3.promise.then推入微任务队列

4.setTimeout推入宏任务队列

5.整段代码执行完毕,开始执行微任务,打印c,遇到setTimeout推入宏任务队列排队等待执行

6.没有可执行的微任务开始执行宏任务,定时器按照延迟时间排队执行

7.打印h j,promise.then推入微任务队列有

8.可执行的微任务,打印i,继续执行宏任务,打印d

9.执行延迟为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执行机制的详细内容,更多关于JavaScript执行机制的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
caller和callee的区别介绍及演示结果
Mar 10 Javascript
JS继承--原型链继承和类式继承
Apr 08 Javascript
使用js完成节点的增删改复制等的操作
Jan 02 Javascript
jQuery点缩略图弹出层显示大图片
Feb 13 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
Nov 24 Javascript
jQuery添加和删除输入文本框标签代码
May 20 Javascript
AngularJS基础 ng-keypress 指令简单示例
Aug 02 Javascript
详解微信小程序 页面跳转 传递参数
Dec 08 Javascript
在vue-cli脚手架中配置一个vue-router前端路由
Jul 03 Javascript
移动前端图片压缩上传的实例
Dec 06 Javascript
vue路由事件beforeRouteLeave及组件内定时器的清除方法
Sep 29 Javascript
深入webpack打包原理及loader和plugin的实现
May 06 Javascript
详解前端任务构建利器Gulp.js使用指南
Apr 30 #Javascript
浅谈node.js中间件有哪些类型
Apr 29 #Javascript
JavaScript实现简单图片切换
何时使用Map来代替普通的JS对象
详解Js模块化的作用原理和方案
详解JavaScript中的执行上下文及调用堆栈
JavaScript实现淘宝商品图切换效果
You might like
php 字符串中的\n换行符无效、不能换行的解决方法
2014/04/02 PHP
Thinkphp批量更新数据的方法汇总
2016/06/29 PHP
PHP+Apache+Mysql环境搭建教程
2016/08/01 PHP
javascript 面向对象编程  function是方法(函数)
2009/09/17 Javascript
JavaScript 利用StringBuffer类提升+=拼接字符串效率
2009/11/24 Javascript
扩展easyui.datagrid,添加数据loading遮罩效果代码
2010/11/02 Javascript
浅析js中2个等号与3个等号的区别
2013/08/06 Javascript
原生js ActiveXObject获取execl里面的值
2013/11/01 Javascript
Nodejs中自定义事件实例
2014/06/20 NodeJs
Nodejs关于gzip/deflate压缩详解
2015/03/04 NodeJs
Javascript监视变量变化的方法
2015/06/09 Javascript
jquery关于事件冒泡和事件委托的技巧及阻止与允许事件冒泡的三种实现方法
2015/11/27 Javascript
移动端使用localStorage缓存Js和css文的方法(web开发)
2016/09/20 Javascript
js实现可输入可选择的select下拉框
2016/12/21 Javascript
详解JS中的柯里化(currying)
2017/08/17 Javascript
node.js利用mongoose获取mongodb数据的格式化问题详解
2017/10/06 Javascript
JavaScript DOM元素常见操作详解【添加、删除、修改等】
2018/05/09 Javascript
jQuery使用动画队列自定义动画操作示例
2018/06/16 jQuery
浅谈Webpack核心模块tapable解析
2018/09/11 Javascript
webpack打包nodejs项目的方法
2018/09/26 NodeJs
JS事件流与事件处理程序实例分析
2019/08/16 Javascript
Openlayers测量距离与面积的实现方法
2020/09/25 Javascript
ant design vue中日期选择框混合时间选择器的用法说明
2020/10/27 Javascript
在vue中给后台接口传的值为数组的格式代码
2020/11/12 Javascript
[00:09]DOTA2全国高校联赛 精彩活动引爆全场
2018/05/30 DOTA
[01:09]模型精美,特效酷炫!TI9不朽宝藏Ⅰ鉴赏
2019/05/10 DOTA
[55:44]完美世界DOTA2联赛决赛 FTD vs Phoenix 第二场 11.08
2020/11/11 DOTA
详解在Python程序中自定义异常的方法
2015/10/16 Python
Python自动发送和收取邮件的方法
2020/08/12 Python
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
英国独特家具和家庭用品购物网站:Cuckooland
2020/08/30 全球购物
中专生职业生涯规划书范文
2013/12/29 职场文书
家长寄语大全
2014/04/02 职场文书
个人委托书范文
2015/01/28 职场文书
2015暑期社会实践调查报告
2015/07/14 职场文书
新手必备之MySQL msi版本下载安装图文详细教程
2021/05/21 MySQL