javascript引擎

最近在了解javascript引擎,在这里跟大家分享一下我学习到有关于javascript引擎的知识。

首先javascript引擎是一种为解释和执行javascript代码设计的虚拟机,javascript引擎一般包含以下这几个部分。

1、编译器,主要将源代码编译成抽象语法树,有些引擎还会将抽象语法树转换成字节码。

2、解释器,主要解释执行字节码,依赖垃圾回收机制。

3、JIT工具,将字节码或抽象语法树转换成本地代码。

4、垃圾回收器和分析工具,负责垃圾回收和收集引擎中信息,改善引擎的性能。

其次javascript是单线程语言,浏览器中一个页面在不开启新的线程下,永远都是一个线程在执行js代码。但是浏览器是多进程的。

为什么浏览器采用的是多进程而不是单进程呢?

第一,不稳定,浏览器的所有功能都在一个进程里,采用多线程方式去进行的话,如果一个线程崩毁,就会影响其他线程的正常运行,从而导致进程终止(线程同步、线程不安全、线程死锁)。

第二,不流畅,浏览器的页面渲染、javascript解释运行,插件等功能都在同一个进程进行,就会导致线程之间互相抢占资源,阻塞线程运行,从而导致整个浏览器失去响应、卡顿。

第三,不安全,多进程的好处就是容易隔离,每个进程都有自己的资源,相互不干扰,如果是单进程的话,只有出现漏洞,那么进程里面的资源就会被曝光,从而失去了安全性。(想进一步了解,关键字:浏览器安全)

浏览器包含哪些进程呢?

1、浏览器进程(只有一个):浏览器的主进程,负责浏览器界面显示,与用户交互(如前进或者后退页面)、管理各个页面,创建和销毁其他进程、将渲染进程在内存得到Bitmap,绘制到用户界面上、网络资源的下载。

2、第三方插件进程:每种类型的插件对应一个进程,只有在使用插件时才会创建。

3、GPU进程:用于3D绘制。

4、浏览器渲染进程(浏览器内核):内部是多线程,默认一个tab页面对应一个进程,互不影响(有些进程会被合并),对页面进行渲染,执行脚本,事件处理。

既然浏览器渲染进程是多线程,那么它包括哪些线程呢?(主要的线程)

图1 (参考图片)

1、GUI渲染线程

负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制页面等。

当界面需要重绘或由于某种操作进行回流,该线程就会执行。

GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时,GUI线程就会被挂起,GUI更新任务会被保存在一个队列,等JS引擎空闲时立刻被执行。

2、JS引擎线程

负责解析javascript脚本,处理javascript脚本程序。JS引擎一直在等任务队列的任务到来,然后进行处理,一个浏览器渲染进程什么时候都是只有一个js线程运行js程序(基于事件驱动单线程)。

3、事件触发线程

用来控制事件循环,当js引擎执行代码(setTimeOut或者鼠标点击、ajax)时,会将对应任务添加到事件线程中,当事件符合触发条件被触发时,该线程就会将事件添加任务队列的队尾,等待js引擎处理,而任务队列里的任务只有js引擎空闲时才会去执行。

4、定时触发器线程

用来帮函数setInterval与setTimeout计时,计时完毕后,事件触发线程会添加任务队列,等带js引擎空闲时执行。W3C在HTML标准中规定,setTimeout低于4ms的时间间隔算为4ms。

5、异步http请求线程

遇到异步http请求会交给该线程去处理,如果监听到状态码变更,如果有回调函数,事件触发线程会将回调函数放到任务队列的尾部等待js引擎处理。

在运行javascript代码时,实际上要维护一组用于执行 JavaScript 代码的代理,每个代理由一组执行上下文的集合、执行上下文栈、主线程、一组可能创建用于执行 worker 的额外的线程集合、一个任务队列以及一个微任务队列构成。除了主线程(某些浏览器在多个代理之间共享的主线程)之外,其它组成部分对该代理都是唯一的。

javascript存在异步执行,通过事件循环机制(event loop)实现执行。

事件循环Event loop机制:

首先,javascript任务分为同步任务和异步任务。

1)同步任务:只有等待主线程执行完上一个任务,下一个任务才能执行,不然下一个任务就会一直等待。

2)异步任务:不用等待主线程执行完上一个任务,下一个任务可以被另一个线程执行,一旦下一个任务执行,则通知主线程结果进行下一步操作(例如执行回调函数)。

主线程在执行时,会依靠执行上下文栈(存放全局执行上下文和函数执行上下文),同步任务放在这个执行上下文栈,除此之外,还会有一个任务队列,异步任务会放在这个任务队列,一旦执行上下文栈没有任务了,主线程没有执行同步任务(空闲下来),任务队列里的异步任务就会到执行上下文栈,主线程去执行异步任务的回调函数(例如鼠标点击事件、ajax回调函数)。

参考图2,图3:

图2(参考图片)

图3(参考图片)

但是到了ES6版本,引入promise,从而有了一个新的概念microtask(微任务),在同步任务和异步任务的基础上再更加细分成任务(因为要跟微任务的名字做区分,也叫宏任务)和微任务。

下面 MDN文档 对宏任务和微任务的解释。

MDN文档的解释  

 总的来说,就是一段javascript代码、一个事件(例如鼠标点击事件)、setInterval、setTimeout都是一个宏任务,然后setInterval、setTimeout和事件是可以将回调函数放入到宏任务队列里,等待下一轮事件循环执行。

宏任务和微任务的执行顺序:

 MDN文档的解释

先是处理完宏任务队列里的宏任务,然后再去处理微任务队列里的微任务,最后再去处理渲染和绘制操作。

参考图4:

 图4(参考图片)

使用微任务应当注意:

MDN文档的解释 

 当还在执行微任务并且微任务队列不为空时,还可以继续向微任务队列放入微任务,但是要进行下一个事件循环,得等到微任务队列为空,所以就会容易造成无尽循环,所以使用微任务还得谨慎。

哪些javascript代码是宏任务、哪些是微任务呢?

宏任务:setTimeout、setInterval、UI事件、同步javascript代码等,由宿主(浏览器、node)发起

微任务:Promise.then、process.nextTick,由javascript引擎发起

这是我对javascript引擎的初步认识,后续还会继续更新。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值