我查看了AVM2概述文件 (第4.11章,第33页),发现了关于init_scope_depth的如下内容
init_scope_depthinit_scope_depth字段定义可在方法中访问的相对于max_scope_depth的最小范围深度。max_scope_depthmax_scope_depth字段定义了可在方法中访问的最大范围深度。max_scope_depth和init_scope_depth之间的差异决定了本地作用域堆栈的大小。
我还在ActionScript 3.0圣经书上遇到了一个关于范围链的引文,我认为它与init_scope_depth有关,并说:
范围链,如图2-1所示,是一个内部设备,用于在函数执行期间管理变量范围。 当引用变量时,Flash以最近调用的函数开始,并检查变量声明。如果在大多数本地作用域中找不到该值,它会将一个级别移到调用该函数的父函数上,并在那里进行检查。此过程一直持续到范围链一直被检查到全局范围为止。
如图所示,我们的范围顺序是,从上到下:
function scope -> parent function(s) scope (if any) -> instance of the class calling the function -> static instance of the class calling the function -> global scope
还请注意,范围链可以有更多的级别,这取决于类继承。
现在我的问题来了:
我一直在使用和RABCDAsm,在一个名为Data的包中有一个名为Global的类。该类不扩展任何其他类,而是实现一个接口。在这个类中,有普通的方法和静态的方法。我注意到静态方法将initscopedepth设置为3,而普通方法将initscopedepth设置为4。(注意:这些值由编译器设置,如AVM2概述文件第4.11章所解释)。
我的猜测是,最初的范围是:
method -> instance of class -> static instance of class (static variables) -> global
但我不确定,我想知道是否有人能证实这一点。
这也给我带来了另一个问题。所有方法code块,包括普通方法和静态方法,都从代码开始:
getlocal_0
pushscope(注意:在这2条指令之后,不管方法是以什么方式开始的。)这是否是因为,对于普通对象,它是将this推到范围堆栈上,而对于静态方法,则是将类的静态实例推到范围堆栈上?若然,为甚麽要这样做呢?
发布于 2020-07-05 17:52:37
好吧,我相信经过进一步的研究和思考,我已经找到了答案。这个谜题的关键是想出另外两件事。
Object类,如这本书中所解释的那样。max_scope_stack值的空间,如AVM2概述的第3.3.3章所解释的那样。因此,初始作用域深度为:global -> Object class -> MyClass class (static instance)
因此,本例中的初始作用域深度为3。我注意到类之外的函数的初始作用域深度为1(仅限于全局范围)。非静态的方法的初始作用域深度为4(它们也有MyClass对象)。
因为当我们输入一个方法时,范围堆栈是空的,而且由于寄存器0保存了this对象(在静态方法的情况下是静态实例,或者如果您愿意的话,类本身),所以我们必须将该对象推到范围堆栈上,以便能够访问其作用域链上的所有变量和方法。当然,我们有方法本身的范围,这使得最大范围深度为4。
https://stackoverflow.com/questions/62665206
复制相似问题