JavaScript是如何执行的——V8引擎的执行
浏览器内核是由两部分组成的,以webkit为例:
- WebCore:负责HTML解析、布局、渲染等等相关工作
- JavaScriptCore:解析、执行JavaScript代码
有一个强大的JavaScript引擎就是v8引擎
V8引擎的执行原理
1.什么是V8引擎
- 是用C++编写的高性能JavaScript和WebAssembly引擎
- 可以实现JavaScript和WebAssembly在多个系统上的运行
- 可以独立运行也可以嵌入到任何C++应用程序中
2.编译过程
- JavaScript源代码
- 解析(Parse)成AST抽象语法树
- 点火(Ignition)过程编译成字节码(字节码可以到处运行了)
- V8引擎会收集信息,将常用的代码通过TurboFan成优化过的机器码(不用再次解析)
V8引擎的架构
1.Parse模块
会将JavaScript代码转换成AST,如果函数没有被调用,是不会被转换成AST的
2.Ignition解释器
会将AST转换成ByteCode(字节码),这里同时会收集TurboFan优化所需要的信息,如果函数只调用一次,Ignition会解释执行ByteCode
3.TurboFan编译器
会将字节码编译为CPU可以直接执行的机器码,如果一个函数被多次调用,就会被标记为热点函数。会被其转换为被优化的机器码,但是,如果在函数执行时,类型发生了变化,这里机器码实际上也会被还原成字节码
4.垃圾回收器
JavaScript在引擎中执行的过程
1.初始化全局对象
js引擎会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO),该对象所有的作用域都可以访问。里面会包含Date、Array、String、Number、setTimeout等等,其中还有一个window指向自己。
2.全局代码执行前后流程
(1)js引擎内部有一个执行上下文栈(ECS),用于执行代码的调用栈;
(2)全局的代码块为了执行会构建一个全局执行上下文(GEC),只要你想运行一个函数,都要先创建一个执行上下文;
(3)每一次执行上下文会关联一个变量对象(VO),变量和函数声明会被添加到这个VO对象中,对于全局上下文GEC来说,此时关联的就是GO;
(4)在代码运行之前,引擎会在GO中声明变量和函数对象,但是此时变量的值为underfind,函数指向的是函数对象的地址,函数是先被声明的;
(5)执行上下文处理关联VO,还会关联一个作用域链和this,然后开始执行代码;
3.函数执行前后过程
(1)创建函数执行上下文(FEC);
(2)进入一个FEC时,会创建一个AO对象,这个对象会使用arguments作为初始化,并且初始值是传入的参数,这个AO对象会作为执行上下文的VO来存储变量;
(3)执行代码;
4.作用域和作用域链
当进入一个执行上下文时,执行上下文也会管理一个作用域链(Scope Chain),作用域链是一个对象列表,用于变量标识符的求值;
当进入一个执行上下文时,做个作用域链被创建,并且根据代码类型,添加一系列的对象,这里要注意,在一个函数被创建时作用域链就确定了,而不是说和this指向一样。
