在JavaScript: Understanding the Weird Parts中,讲师解释了变量的内存是在所谓的创建阶段设置的(并且undefined
已分配);然后执行阶段发生。但是,当我们不知道变量稍后会指向哪个值时,为什么这很有用呢?
显然,变量可以指向许多不同的东西 - 例如一个短字符串一直到一个深度嵌套的对象结构 - 我认为它们可以在他们需要的内存量上大相径庭。
如果逐行执行 - 包括变量赋值 - 仅在稍后的执行阶段发生,那么初始创建阶段如何知道如何设置内存?或者,是否仅为每个变量名称/值对中的名称留出内存,并且以不同方式管理值的内存?
答案 0 :(得分:5)
教师指的是Google Chrome's V8 engine(正如他在视频中使用它所证明的那样)。
V8引擎使用多种优化方法来促进内存管理。首先,它将编译JavaScript代码,在编译期间,它将确定需要创建多少变量(隐藏类,以后更多)。这些将决定最初分配的内存量。
V8首次执行时,会将JavaScript源代码直接编译为机器代码。没有中间字节代码,没有解释器。属性访问由内联缓存代码处理,可以在V8执行时使用其他机器指令进行修补。 的 1 强>
第一组是通过导航JavaScript代码来创建的,以确定有多少不同的对象“形状”。任何没有原型的东西都被认为是“过渡物体形状”
对象编码的主要方式是将隐藏的类(描述)与对象(内容)分开。实例化新对象时,使用与同一构造函数中的先前对象相同的初始隐藏类创建它们。随着属性的添加,对象从隐藏类转换到隐藏类,通常遵循所谓的“转换树”中的先前转换。 的 2 强>
相反,如果对象 具有原型,那么它将分别跟踪其特定形状。
原型有两个主要阶段:设置和使用。设置阶段中的原型被编码为字典对象。任何对原型的直接访问或通过原型链访问都会将其转换为使用状态,从而确保从现在开始的所有此类访问都很快。 的 2 强>
编译器基本上将所有可能的变量读取为这两种可能的形状之一,然后分配必要的内存量以便于实例化这些形状。
一旦设置了第一组形状,V8就会利用他们所谓的“快速属性访问”来构建在构建期间设置的第一组变量(隐藏类)。
为了减少访问JavaScript属性所需的时间,V8会在幕后动态创建隐藏类 3
使用隐藏类有两个好处:属性访问不需要字典查找,它们使V8能够使用经典的基于类的优化,内联缓存 3
因此,在编译期间并不是所有的内存使用都是已知的,只有为隐藏类的核心集分配了多少内存。这种分配将随着代码的执行而增长,包括赋值,内联缓存未命中和转换为字典模式(当为对象分配了太多属性时会发生这种情况,以及其他一些细微差别因素)。
<子> 1。动态机器代码生成,https://github.com/v8/v8/wiki/Design%20Elements#dynamic-machine-code-generation
<子> 2。在V8中设置原型,https://medium.com/@tverwaes/setting-up-prototypes-in-v8-ec9c9491dfe2
<子> 3。快速财产访问,https://github.com/v8/v8/wiki/Design%20Elements#fast-property-access
答案 1 :(得分:0)
当任何程序执行时,执行时间我们称之为运行时间。在运行时或处理时,处理器处理代码并与内存通信。 Procesor从内存中获取代码,处理代码,结果返回内存,获取其他代码。所有的运行时间,内存中的一些空间变得更加严肃;一些空间变为零,一些变量获得新值,一些变量被删除等。运行时间内工作内存量一直在变化。