v8是一款主流的javascript
执行引擎,我们在学习javascript
的过程中,v8也是必须要了解的。
接下来我们先看一张图,先了解V8引擎执行的全过程
工作流从Scanner开始
1.scanner是一个扫描器
,对js代码进行词法分析,把代码分析成不同的tokens,拆解成最小单元
2.parser是解析器
,语法分析,语法校验,会得到一个语法树
3.preparser是预解析
,比如很多函数我们定义了但是没有用到,就会跳过这些函数的解析,不会生成AST抽象语法树
4.ignition是解释器
,把抽象语法树转换成字节码
5.turboFan是编译器模块
,把字节码转换成汇编代码,之后就是执行代码
插一嘴,什么是预解析和全量解析
什么是全量解析?
1.解析被使用的代码
2.生成AST抽象语法树
3.构建具体scopes信息,变量引用,声明等
4.抛出所有语法错误
上面都是V8引擎在执行代码前做的工作,之后我们来说说V8是怎么执行代码的
堆栈准备
1.js执行环境,打开浏览器之后在内存中开辟
2.执行环境栈(ECS)
3.执行上下文
4.VO(G),全局变量对象
js执行过程可以看做是往一个桶中加水,然后再倒水的过程。所以先装入的水,最后被倒出来。如上所示:
1.在执行环境栈中开辟部分空间来当做全局执行上下文,该上下文包含全局变量和 window对象
2.之后从上往下执行代码,全局变量就存放在VOG全局对象中,遇到原始数据类型时,就直接在栈空间存放数据;遇到引用变量时,就会去开辟堆内存来存储这些数据,变量就会引用这个内存的地址,是一个十六进制的字符串,相当于门牌号。
3.重点说一下函数,函数也是一个对象,当定义一个函数时,它也会去堆内存开辟一个空间来存放函数的函数体,而且函数的声明和赋值是理解执行的,所以定义函数可以在调用函数之后,也不会报错。
4.上面都是声明环节,之后就是函数执行环节了,函数执行会形成自己的私有上下文,如图所示,函数入栈会执行6步操作。
5.当然函数嵌套就有可能产生闭包,就是当前上下文的变量被外部上下文引用了,且当前上下文无法出栈。所以啊,以前有一种说法,不能过多使用闭包,会造成内存泄漏,问题就出在这个地方了。
6.当一个函数执行完毕,如果没有产生闭包的话,那么他的私有上下文就会出栈了,被清理。它内部产生的引用数据会等待GC回收。
这就是整个执行的过程啦!