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 相关文章推荐
Jquery作者John Resig自己封装的javascript 常用函数
Nov 09 Javascript
jquery插件tytabs.jquery.min.js实现渐变TAB选项卡效果
Aug 25 Javascript
延时加载JavaScript代码提高速度
Dec 27 Javascript
Bootstrap路径导航与分页学习使用
Feb 08 Javascript
JS设置随机出现2个数字的实例代码
Jul 19 Javascript
浅谈vue的iview列表table render函数设置DOM属性值的方法
Sep 30 Javascript
基于vue-cli创建的项目的目录结构及说明介绍
Nov 23 Javascript
vue 实现全选全不选的示例代码
Mar 29 Javascript
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
Feb 14 jQuery
详解js常用分割取字符串的方法
May 15 Javascript
Element Popover 弹出框的使用示例
Jul 26 Javascript
浅谈vue中document.getElementById()拿到的是原值的问题
Jul 26 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
PHP4实际应用经验篇(9)
2006/10/09 PHP
discuz7 phpMysql操作类
2009/06/21 PHP
php数组函数序列之array_intersect() 返回两个或多个数组的交集数组
2011/11/10 PHP
使用PHP求两个文件的相对路径
2013/06/20 PHP
eaglephp使用微信api接口开发微信框架
2014/01/09 PHP
php截取指定2个字符之间字符串的方法
2015/04/15 PHP
IE不支持getElementsByClassName最终完美解决方案
2012/12/17 Javascript
谈谈关于JavaScript 中的 MVC 模式
2013/04/11 Javascript
get(0).tagName获得作用标签示例代码
2014/10/08 Javascript
基于jquery实现发送文章到手机的代码
2014/12/26 Javascript
jQuery Ajax使用实例
2015/04/16 Javascript
bootstrap datepicker 与bootstrapValidator同时使用时选择日期后无法正常触发校验的解决思路
2016/09/28 Javascript
vue.js 使用v-if v-else发现没有执行解决办法
2017/05/15 Javascript
JS匿名函数和匿名自执行函数概念与用法分析
2018/03/16 Javascript
使用js实现一个简单的滚动条过程解析
2019/09/10 Javascript
解决vue使用vant下拉框van-dropdown-item 绑定title值不变问题
2020/08/05 Javascript
python同时给两个收件人发送邮件的方法
2015/04/30 Python
python 删除非空文件夹的实例
2018/04/26 Python
Python实现的统计文章单词次数功能示例
2019/07/08 Python
浅谈Django中view对数据库的调用方法
2019/07/18 Python
python实现桌面气泡提示功能
2019/07/29 Python
python中安装django模块的方法
2020/03/12 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
2020/05/26 Python
Python实现中英文全文搜索的示例
2020/12/04 Python
HTML5 video视频字幕的使用和制作方法
2018/05/03 HTML / CSS
构造方法和其他方法的区别?怎么调用父类的构造方法
2013/09/22 面试题
2014年九一八事变演讲稿
2014/09/14 职场文书
单位授权委托书范本
2014/09/26 职场文书
营销经理工作检讨书
2014/11/03 职场文书
大学团日活动总结书
2015/05/11 职场文书
2015年电话客服工作总结
2015/05/18 职场文书
百年孤独读书笔记
2015/06/29 职场文书
2015国庆66周年宣传语
2015/07/14 职场文书
员工给公司的建议书
2019/06/24 职场文书
2019年大学推荐信
2019/06/24 职场文书
spring boot实现文件上传
2022/08/14 Java/Android