JavaScript运行机制实例分析


Posted in Javascript onApril 11, 2020

本文实例讲述了JavaScript运行机制。分享给大家供大家参考,具体如下:

第一次写博客

目前研一第二学期,大二开始入门前端,然而长久以来都是对于框架的简单调用,并未对其进行深入研究,因此,这个博客是作为自我督促的开始。这篇博客的内容源于前段时间写一个微信小程序前端,发现页面的渲染顺序总与自己的预想相违背,因此近期看了一些关于JavaScript运行机制的博客及文档,有了一些基本的框架,接下来就来详细看一下我所了解到的内容。

JavaScript执行顺序

首先,JavaScript是按照顺序,一行一行执行的,且JS只有一条线程,即不可能进行两条代码同时执行,也就是说,在一条代码执行时,它后面的所有代码都需要等待,直到该代码执行结束,后面的才能继续执行。如果是这样,就会导致用户体验度极其不好,例如一个请求发送给服务器,后续代码就会一直等待,直到服务器返回结果,用户才能进行新的操作。

这又是怎么回事呢?

详细解释JavaScript执行机制

JavaScript执行栈

JavaScript是以压栈的方式进行代码的执行的,一开始执行时栈内为空,当执行开始,JS引擎会将代码放入栈底,若该代码包含其他函数的调用,则将被调用的函数放在栈顶,若该代码未包含其他函数的调用,则执行该函数,执行完成后出栈,以此类推,最终直到栈为空。

JavaScript的同步任务和异步任务

事实上,真正的JS内部分为同步任务和异步任务,然而这并没有改变JS单线程的特征。

  • 同步任务:执行后直接返回结果,例:console.log();c = a + b
  • 异步任务:执行后无法立刻返回结果,需要等待一定时间,才能执行回调函数,对返回结果进行操作

系统来说,JS存在一个主线程,它会首先执行所有同步任务,而异步任务都会先进行注册,然后主线程不会等待异步任务执行结果的返回,而是继续执行下面的同步任务(在此过程中,如果异步任务返回结果,接下来的回调函数会放在Event Queue中等待),直到同步任务全部执行完毕,主线程就会从Event Queue读取任务进行执行。该过程会不断循环,即事件循环Event Loop。

事件循环是如何发生的

不觉得奇怪吗,如果按照上述同步任务和异步任务的执行方式,那不是一轮就可以执行完毕吗,又何来的Event Loop?

这是个小细节,异步任务存在多个时,每一个异步任务返回的结果所需的时间都是不同的,这就存在Event Queue以先进先出的形式将返回结果进行排队,第一个异步任务返回结果,那么就将其放在队列的首位,接下来的异步任务紧随其后,就这样排成一队。当主线程空闲时(即同步任务执行完毕后),便从Event Queue中读取事件,放入主线程执行。而循环来自于,当Event Queue执行完毕后,过了一段时间,又有之前的异步任务返回结果,放到Event Queue中,监控器检测到Event Queue为非空,主线程又开始执行Event Queue中的任务。

宏任务和微任务

在解释定义之前,我们先对异步任务进行说明:

  1. 对服务器的异步请求:最常见的异步任务,这涉及前后端的交互,需要服务器对请求进行处理,并返回请求结果
  2. setTimeout和setInterval:延时操作,后者为循环操作(都涉及延时值)
  3. Promise:JS用来处理异步操作的对象
  4. process.nextTick(callback):类似node.js版的"setTimeout",在事件循环的下一次循环中调用 callback 回调函数。

广义上JS分为同步任务和异步任务,在此对任务进行更精细的定义:

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick

在此,之所以提出宏任务和微任务,是为了更好的理解事件循环!

执行过程:

  • 主线程会按顺序先执行第一次循环的宏任务,然后将第一次循环遇到的微任务放入微任务的Event Queue中,将遇到的宏任务放入宏任务Event Queue中,在此特别注意!!第一次循环的宏任务是整体script代码!!;
  • 然后后执行微任务的Event Queue;
  • 第二次循环时,会从宏任务的Event Queue中取出第一个宏任务,然后执行当前宏任务中包含的代码,同样将遇到的微任务放入微任务的Event Queue中,将遇到的宏任务放入宏任务Event Queue中;
  • 再执行当前微任务的Event Queue中的任务;
  • 第三次循环,从宏任务的Event Queue中取出第二个宏任务…(以此循环)

简而言之,就是先执行宏任务,再执行微任务,特别注意两点即可:

  1. 第一次循环的宏任务是整体script代码
  2. 宏任务队列是一次循环执行一条宏任务

这里看个例子:

console.log('1');
 
 setTimeout(function() {
  console.log('2');
  process.nextTick(function() {
   console.log('3');
  })
  new Promise(function(resolve) {
   console.log('4');
   resolve();
  }).then(function() {
   console.log('5')
  })
 })
 process.nextTick(function() {
  console.log('6');
 })
 new Promise(function(resolve) {
  console.log('7');
  resolve();
 }).then(function() {
  console.log('8')
 })
 
 setTimeout(function() {
  console.log('9');
  process.nextTick(function() {
   console.log('10');
  })
  new Promise(function(resolve) {
   console.log('11');
   resolve();
  }).then(function() {
   console.log('12')
  })
 })
 
 //作者:ssssyoki
 //链接:https://juejin.im/post/59e85eebf265da430d571f89
 //来源:掘金

输出顺序为:

1,7,6,8,2,4,3,5,9,11,10,12

总结

在此博客中,或许包含一些你未曾听过的名词或方法,我并未对其进行详细解释。之所以如此,是由于,于我个人,在看一些资料时,经常遇到不懂的东西,我会选择自己进行查阅和理解,这样更有效于记忆和通透的理解,就跟查单词是一样的,如果文本里直接告诉你,反而不会重视。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
js window.onload 加载多个函数的方法
Nov 02 Javascript
Extjs根据条件设置表格某行背景色示例
Jul 23 Javascript
基于Jquery easyui 选中特定的tab
Nov 17 Javascript
基于javascript代码检测访问网页的浏览器呈现引擎、平台、Windows操作系统、移动设备和游戏系统
Dec 03 Javascript
BootStrap Tooltip插件源码解析
Dec 27 Javascript
javascript简写常用的12个技巧(可以大大减少你的js代码量)
Mar 28 Javascript
浅谈vue同一页面中拥有两个表单时,的验证问题
Sep 18 Javascript
js实现京东秒杀倒计时功能
Jan 21 Javascript
ES6 对象的新功能与解构赋值介绍
Feb 05 Javascript
vue组件传值的实现方式小结【三种方式】
Feb 05 Javascript
JavaScript实现缓动动画
Nov 25 Javascript
JavaScript 中的六种循环方法
Jan 06 Javascript
js中调用微信的扫描二维码功能的实现代码
Apr 11 #Javascript
微信公众号中的JSSDK接入及invalid signature等常见错误问题分析(全面解析)
Apr 11 #Javascript
微信分享invalid signature签名错误踩过的坑
Apr 11 #Javascript
vue.js中使用微信扫一扫解决invalid signature问题(完美解决)
Apr 11 #Javascript
vue使用微信扫一扫功能的实现代码
Apr 11 #Javascript
Vue 中 template 有且只能一个 root的原因解析(源码分析)
Apr 11 #Javascript
vue搜索页开发实例代码详解(热门搜索,历史搜索,淘宝接口演示)
Apr 11 #Javascript
You might like
PHP substr 截取字符串出现乱码问题解决方法[utf8与gb2312]
2011/12/16 PHP
php类中的各种拦截器用法分析
2014/11/03 PHP
自己写的php中文截取函数mb_strlen和mb_substr
2015/02/09 PHP
PHP设计模式(七)组合模式Composite实例详解【结构型】
2020/05/02 PHP
Apache+PHP+MySQL搭建PHP开发环境图文教程
2020/08/06 PHP
js技巧--转义符"\"的妙用
2007/01/09 Javascript
js实现一个省市区三级联动选择框代码分享
2013/03/06 Javascript
基于jquery的禁用右键、文本选择功能、复制按键的实现代码
2013/08/27 Javascript
JavaScript-RegExp对象只能使用一次问题解决方法
2014/06/23 Javascript
jQuery排序插件tableSorter使用方法
2017/02/10 Javascript
判断横屏竖屏(三种)
2017/02/13 Javascript
纯js的右下角弹窗实例
2017/03/12 Javascript
CSS3 动画卡顿性能优化的完美解决方案
2018/09/20 Javascript
移动端滑动切换组件封装 vue-swiper-router实例详解
2018/11/25 Javascript
js常用方法、检查是否有特殊字符串、倒序截取字符串操作完整示例
2020/01/26 Javascript
[35:43]2018DOTA2亚洲邀请赛 4.1 小组赛B组 paiN vs Effect
2018/04/03 DOTA
在python的WEB框架Flask中使用多个配置文件的解决方法
2014/04/18 Python
编写Python爬虫抓取豆瓣电影TOP100及用户头像的方法
2016/01/20 Python
使用python绘制3维正态分布图的方法
2018/12/29 Python
python通过TimedRotatingFileHandler按时间切割日志
2019/07/17 Python
使用 Python 处理 JSON 格式的数据
2019/07/22 Python
Python使用import导入本地脚本及导入模块的技巧总结
2019/08/07 Python
python画蝴蝶曲线图的实例
2019/11/21 Python
tensorflow mnist 数据加载实现并画图效果
2020/02/05 Python
浅谈SciPy中的optimize.minimize实现受限优化问题
2020/02/29 Python
Python3操作YAML文件格式方法解析
2020/04/10 Python
详解CSS3实现响应式手风琴效果
2020/06/10 HTML / CSS
路易威登和香奈儿手袋:LuxeDH
2017/01/12 全球购物
如何查询Oracle数据库中已经创建的索引
2013/10/11 面试题
后勤人员自我鉴定
2013/10/20 职场文书
精彩的演讲稿开头
2014/05/08 职场文书
文明城市标语
2014/06/16 职场文书
葬礼主持词
2015/07/02 职场文书
关于拾金不昧的感谢信(五篇)
2019/10/18 职场文书
Redis持久化与主从复制的实践
2021/04/27 Redis
解决pycharm下载库时出现Failed to install package的问题
2021/09/04 Python