详解JavaScript执行模型


Posted in Javascript onNovember 16, 2020

JavaScript执行模型

引言

JavaScript是一个单线程(Single-threaded)异步(Asynchronous)非阻塞(Non-blocking)并发(Concurrent)语言,这些语言效果通过一个调用栈(Call Stack)、一个事件循环(Event Loop)、一个回调队列(Callback Queue)有些时候也叫任务队列(Task Queue)与跟运行环境相关的API组成。

概念

调用栈 Call Stack

调用栈是一个LIFO后进先出数据结构的函数运行栈,它内部的数据结构为函数帧。当在JavaScript中调用一个函数时,它将被压入栈中,当这个函数内部还有另一个函数被调用时,另一个函数将会被压入栈顶,直到其内部没有更多调用,栈顶函数将会被以单线程方式执行并出栈,直到最后一个函数帧出栈。JavaScript语言特性中的单线程就是指的调用栈的单线程运行。

function multiply(a, b) {
 return a * b;
}

function square(n) {
 return multiply(n, n)
}

function printSquare(n) {
 console.log(square(n));
}

printSquare(4);

首先调用栈压入main(),扫描到printSquare()函数调用调用栈压入printSquare(4)printSquare函数内部调用square(n)该函数被压入栈,同理multiply(n, n)函数也被压入栈且没有更多调用,JavaScript引擎开始执行栈顶函数multiply(n, n)返回结果并出栈,以此类推直到main()函数出栈。

调用栈有一个意外情况,当函数递归调用其自身时调用栈将溢出,执行环境将报错。

function foo() {
 foo();
}
foo();

任务队列 Task Queue

任务队列是WebAPI的一部分,也就是说它本身并不是ECMAScript标准的一部分,而是运行环境自行实现的。任务队列是所有回调函数排队执行的FIFO先进先出队列,它的单位是任务(Task),每个任务都关联着一个用于处理这个任务的回调函数。在事件循环(Event Loop)中会将任务队列内的函数压入调用栈执行并出队列,直至为空。

任务队列在浏览器的实现中被分为了宏任务队列(macrotask queue)和微任务队列(microtask queue),它们分别个自承载宏任务(macrotask)和微任务(microtask)的排队,其中宏任务队列与宏任务又被默认为常规的任务队列与任务。

当调用栈内所有调用都完成执行后,事件轮询会在每次处理宏任务队列的一个宏任务后处理微任务队列的全部微任务,也就是微任务基本会在宏任务处理之前被处理。微任务处理中间不会被UI或网络事件处理被执行,微任务执行是连续的。

会被添加到宏任务的方法的回调有:

  • script:script标签中的代码解析运行
  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI rendering:UI渲染,每16.6ms放到队列上一次,60fps,如果调用栈被占用则会被阻塞

会被添加到微任务的Web API方法有:

会被添加到微任务的Web API方法有:

  • process.nextTick:Node提供的
  • Promise
  • Object.observe
  • MutationObserver

微任务只会从我们编写的代码中产生,宏任务既可能从我们编写的代码中产生也可能从浏览器本身事件、渲染、IO产生。

事件循环 Event Loop

事件循环是JavaScript的事件处理机制,它会一直轮询消息队列,当满足调用栈为空且消息队列不为空时,它将把消息队列队头的消息压入执行栈。这样的机制保证了函数不会被中断,不会有线程切换带来的数据不一致等情况

事件循环在调用栈为空时轮询,顺序为

1.找到任务队列(宏任务队列)的最早被添加的任务并将其添加到调用栈执行

2.执行所有微任务队列内的任务

  • 当微任务队列不为空时找到微任务队列最早被添加的任务并将其添加到调用栈执行

3.渲染所有变化
4.如果宏任务队列为空等待宏任务出现
5.返回步骤1

JavaScript运行时 Runtime

详解JavaScript执行模型

浏览器的JavaScript代码执行也就是调用栈与堆(用于储存变量对象等)由JavaScript引擎提供,用的比较多的是谷歌的V8引擎,Chrome、Edge浏览器、Nodejs均使用该引擎。

事件循环Event Loop、任务队列Task Queue(回调队列Callback Queue)、WebAPI或Node API由运行环境提供。

以上就是详解JavaScript执行模型的详细内容,更多关于JavaScript执行模型的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JS文本框不能输入空格验证方法
Mar 19 Javascript
返回上一页并自动刷新的JavaScript代码
Feb 19 Javascript
文本框水印提示效果的简单实现代码
Feb 22 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
Oct 10 Javascript
浅谈bootstrap使用中的一些问题以及解决过程
Oct 18 Javascript
浅谈Angular的$q, defer, promise
Dec 20 Javascript
vue2的todolist入门小项目的详细解析
May 11 Javascript
原生JS获取元素的位置与尺寸实现方法
Oct 18 Javascript
浅谈Angular6的服务和依赖注入
Jun 27 Javascript
小程序实现留言板
Nov 02 Javascript
Element input树型下拉框的实现代码
Dec 21 Javascript
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
Jul 19 Javascript
Vue 实现拨打电话操作
Nov 16 #Javascript
微信小程序实现页面左右滑动
Nov 16 #Javascript
Vertx基于EventBus发送接受自定义对象
Nov 16 #Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
Nov 16 #Javascript
angular8.5集成TinyMce5的使用和详细配置(推荐)
Nov 16 #Javascript
js实现纯前端压缩图片
Nov 16 #Javascript
Vue基于localStorage存储信息代码实例
Nov 16 #Javascript
You might like
PHP中文编码小技巧
2014/12/25 PHP
PHP的Yii框架的常用日志操作总结
2015/12/08 PHP
JS 有名函数表达式全面解析
2010/03/19 Javascript
jQuery 获取对象 定位子对象
2010/05/31 Javascript
jQuery图片预加载 等比缩放实现代码
2011/10/04 Javascript
javascript禁用键盘功能键让右击及其他键无效
2013/10/09 Javascript
jQuery分别获取选中的复选框值的示例
2014/06/17 Javascript
javascript制作游戏开发碰撞检测的封装代码
2015/03/31 Javascript
JS实现兼容各浏览器解析XML文档数据的方法
2015/06/01 Javascript
原生js获取浏览器窗口及元素宽高常用方法集合
2017/01/18 Javascript
react.js 翻页插件实例代码
2017/01/19 Javascript
Vue.js仿微信聊天窗口展示组件功能
2017/08/11 Javascript
详解react-native-fs插件的使用以及遇到的坑
2017/09/12 Javascript
JS高级技巧(简洁版)
2018/07/29 Javascript
记录一篇关于redux-saga的基本使用过程
2018/08/18 Javascript
angular6的响应式表单的实现
2018/10/10 Javascript
基于vue 动态菜单 刷新空白问题的解决
2020/08/06 Javascript
Python入门之modf()方法的使用
2015/05/15 Python
Python实现E-Mail收集插件实例教程
2019/02/06 Python
windows下安装Python虚拟环境virtualenvwrapper-win
2019/06/14 Python
python如果快速判断数字奇数偶数
2019/11/13 Python
Microsoft新加坡官方网站:购买微软最新软件和技术产品
2016/10/28 全球购物
Moda Operandi官网:美国奢侈品电商,海淘秀场T台同款
2020/05/26 全球购物
妇科医生自荐信
2013/11/05 职场文书
行政前台岗位职责
2013/12/04 职场文书
借款协议书
2014/04/12 职场文书
一年级学生评语
2014/04/23 职场文书
初中班主任经验交流材料
2014/05/16 职场文书
2014年招商工作总结
2014/11/22 职场文书
事业单位个人总结
2015/02/12 职场文书
英语导游词
2015/02/13 职场文书
致地震灾区的慰问信
2015/03/23 职场文书
2015年驾驶员工作总结
2015/04/29 职场文书
2015年节能减排工作总结
2015/05/14 职场文书
Python破解极验滑动验证码详细步骤
2021/05/21 Python
详解Mysql数据库平滑扩容解决高并发和大数据量问题
2022/05/25 MySQL