详解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点击页面其它地方将某个显示的DIV隐藏
Jul 12 Javascript
IE中的File域无法清空使用jQuery重设File域
Apr 24 Javascript
javascript实现仿IE顶部的可关闭警告条
May 05 Javascript
JQuery中clone方法复制节点
May 18 Javascript
jquery+css3实现会动的小圆圈效果
Jan 27 Javascript
基于Bootstrap+jQuery.validate实现表单验证
May 30 Javascript
把vue-router和express项目部署到服务器的方法
Feb 21 Javascript
vue.js获得当前元素的文字信息方法
Mar 09 Javascript
vue 自定义提示框(Toast)组件的实现代码
Aug 17 Javascript
在React中写一个Animation组件为组件进入和离开加上动画/过度效果
Jun 24 Javascript
JavaScript中的相等操作符使用详解
Dec 21 Javascript
关于Vue Router的10条高级技巧总结
May 06 Vue.js
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使用fopen创建utf8编码文件的方法
2014/10/31 PHP
PHP实现Soap通讯的方法
2014/11/03 PHP
php中静态类与静态变量用法的区别分析
2015/01/15 PHP
php实现RSA加密类实例
2015/03/26 PHP
浅谈PHP中foreach/in_array的使用
2015/11/02 PHP
php实现的PDO异常处理操作分析
2018/12/27 PHP
js遍历、动态的添加数据的小例子
2013/06/22 Javascript
JS 实现Table相同行的单元格自动合并示例代码
2013/08/27 Javascript
jQuery实现可编辑的表格实例讲解(2)
2015/09/17 Javascript
layui表格实现代码
2017/05/20 Javascript
Vue 拦截器对token过期处理方法
2018/01/23 Javascript
angular6开发steps步骤条组件
2019/07/04 Javascript
JS算法教程之字符串去重与字符串反转
2020/12/15 Javascript
[06:40]2014DOTA2西雅图国际邀请赛 DK战队巡礼
2014/07/07 DOTA
Python translator使用实例
2008/09/06 Python
Python利用公共键如何对字典列表进行排序详解
2018/05/19 Python
tensorflow 输出权重到csv或txt的实例
2018/06/14 Python
python2与python3共存问题的解决方法
2018/09/18 Python
python 将大文件切分为多个小文件的实例
2019/01/14 Python
利用python画出AUC曲线的实例
2020/02/28 Python
python 进程池pool使用详解
2020/10/15 Python
波兰品牌内衣及泳装网上商店:Astratex.pl
2017/02/03 全球购物
美国知名平价彩妆品牌:e.l.f. Cosmetics
2017/11/20 全球购物
瑞典的玛丽小姐:Miss Mary of Sweden
2019/02/13 全球购物
德国的大型美妆个护电商:Flaconi
2020/06/26 全球购物
世界上最大的皮肤科医生拥有和经营的美容网站:LovelySkin
2021/01/03 全球购物
设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
2014/12/30 面试题
致百米运动员广播稿5篇
2014/10/13 职场文书
项目负责人岗位职责
2015/02/15 职场文书
防卫过当辩护词
2015/05/21 职场文书
赤壁观后感(2)
2015/06/15 职场文书
心理健康教育培训研修感言
2015/11/18 职场文书
《学会生存》读后感3篇
2019/12/09 职场文书
HashMap实现保存两个key相同的数据
2021/06/30 Java/Android
利用Python将list列表写入文件并读取的方法汇总
2022/03/25 Python
Windows Server 2016服务器用户管理及远程授权图文教程
2022/08/14 Servers