JavaScript的执行过程
2021-12-07 16:22:58 5 举报
JavaScript的执行过程
作者其他创作
大纲/内容
栈:栈是临时空间,主要存储局部变量和函数调用,内存小单存储连续,操作起来方便,一般由系统自动分配,回收。基本数据类型都保存在栈内存中,引用数据类型保存在堆内存中。堆:这里用来存储对象和动态数据,这是内存中最大的区域,并且是GC(Garbage collection 垃圾回收)工作的地方。不过,并不是所有的堆内存都可以进行GC,只有新生代和老生代被GC管理。堆可以进一步细分为下面这样:新生代空间:是最新产生的数据存活的地方,这些数据往往都是短暂的。这个空间被一分为二,然后被Scavenger(Minor GC)所管理。老生代空间:是从新生代空间经过至少两轮Minor GC仍然存活下来的数据,该空间被Major GC(Mark-Sweep & Mark-Compact)管理,稍后会介绍。Old data space: 存活下来的只包含数据的对象。大对象空间: 这是比空间大小还要大的对象,大对象不会被gc处理。代码空间:这里是JIT所编译的代码。这是除了在大对象空间中分配代码并执行之外的唯一可执行的空间。map空间:存放 Cell 和 Map,每个区域都是存放相同大小的元素,结构简单。垃圾回收算法:计数法,标记清理,复制清除等
Orinoco: 垃圾回收器
语法分析Parser:将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了语法结构的树。这个树就是抽象语法树。{ \"type\": \"Program\
TurboFan:complier,即编译器。利用Ignition所收集的类型信息,将Bytecode转换为优化的汇编代码:1:如果一个函数被多次调用,则被标记为热点函数,那么经过TurboFan的转换优化的机器码,提高代码的执行能力。2:但是,机器码实际上也会被还原为bytecode--比如我们定义了number类型,但是之后我们赋值为字符串类型,之前的机器码并不能正确处理,就会逆向转换
可以使用node --print-bytecode xxx.js来查看生成的字节码,这里涉及到一个重要的概念: JIT(just-in-time)一边解释,一边执行:1.在js引擎中增加一个监视器(也交分析器),监视器监控代码的运行情况,记录代码一共运行了多少次、如何运行等信息,如果同一行代码只运行了少数次,则被标记为warm,如果多次运行则被标记hot2.(基线编译器)如果一段代码变成了warm,那么JIN就会把他送到基线编译器中去编译,并且把编译结果存储起来。比如,监视器监视到了某行、某个变量执行同样的代码,使用同样的变量类型,那么就会把编译后的版本,替换这一行代码的执行,并且存储。3.(优化编译器)被标记为hot的代码,会被送进优化编译器,生成一个更快速更高效的代码版本出俩,并且存储。4.(反优化)比如我们定义了number类型,但是之后我们赋值为字符串类型,之前的机器码并不能正确处理,就会逆向转换
执行上下文:遇到函数执行的时候,就会创建一个执行上下文。执行上下文是当前js代码被解析和执行时所在环境的抽象概念。javascript中有三个执行上下文:全局执行上下文(只有一个),函数执行上下文,eval。执行上下文的创建分为两个阶段: 创建阶段和执行阶段。创建阶段:在任意代码执行时,执行上下文处于创建阶段,在创建阶段总共发生了三件事情:1.确定this的值,也成为This Binding。2.LexicalEnvironment(词法环境)组件被创建。(主要用来登记 var function变量声明)3.variableEnvironment(变量环境)组件被创建。(主要登记let const class等变量声明)在Es6之前没有块级作用于,Es6以后我么可以使用let const来声明款及作用域,有这两个此法环境是为了实现块级作用域的同事不影响var变量声明和函数声明,具体如下:首先在一个正在运行的执行上下文内,词法环境由 词法环境和变量环境构成,用来登记所有的变量声明。当执行到块级代码的时候,会先让词法环境记录下来,记录为oldEnv创建一个新的词法环境(outer指向oldEnv),记录为newEnv,并将newEnv设置为正在执行上线文的词法环境块级代码内的let const会登记在newEnv里面,但是var,函数声明还是登记在原来的变量环境里面。块级代码执行结束后,将oldEnv还原为正在执行上下文的词法环境。
词法分析Scanner:将字符转组成的代码分解成词法单元(token):[ { \"type\": \"Keyword\
JS执行过程(V8引擎工作原理)
收藏
0 条评论
下一页