所以,我一直在玩Flash,浏览文档,以及所有这些,并注意到ENTER_FRAME事件似乎违背了我对确定性宇宙的期望。
请看以下示例:
(new MovieClip()).addEventListener(Event.ENTER_FRAME,
function(ev) {trace("Test");});
请注意,此匿名MovieClip未添加到显示层次结构中,并且对它的任何引用都会立即丢失。
它实际上会一帧一次打印“测试”,直到它被垃圾收集。这有多疯狂?这种行为实际上取决于垃圾收集器何时会出现无法预测的疯狂行为!是否有更好的方法来创建间歇性故障? 严重。
我的两个理论是,DisplayObject类存储对其所有实例的弱引用,以便调度ENTER_FRAME事件,或者,更疯狂的是,Flash播放器实际上每帧扫描堆,寻找ENTER_FRAME侦听器。
任何强化的Actionscript开发人员能否告诉我这是如何工作的? (也许是为什么 - 他们认为这是个好主意?)
答案 0 :(得分:4)
简短回答:你得到了你要求的东西。
您的MovieClip是“匿名的”,就像您所说的那样,并不会改变垃圾收集的工作方式。
你的两个理论都错了。它更简单。您要求您的MovieClip实例在输入框架时通知您。引自docs:
播放头播放时调度 进入一个新的框架。如果是播放头 不动,或者只有一个 框架,此事件已分派 不断地与...一起 帧率。此事件已发送 同时显示所有显示对象 坚持这个事件。
这就是正在发生的事情。
MovieClip等对象是堆分配的。如果在局部变量中存储对它的引用,则引用将存在于堆栈中,并且在从函数返回时将超出范围。您将无法引用该对象,但该对象仍然存在于堆中。因此,无论您是否存储对mc实例的引用,都不会改变堆和垃圾收集如何工作的基本事实。
现在,由于此对象没有强烈的参考,因此该对象可忽略用于集合。这并不意味着当函数返回时会收集。
由于对象仍然存在,它将继续发送事件,因为你要求它。一旦收集,自然地,处理程序中的代码将不再被执行。
修改强>
我说你的两个理论都错了。我认为从Actionscript的角度来看就是这种情况。然而,在玩家级别,玩家必须跟踪必须触发某些事件的对象,所以是的,它必须存储对所述对象的内部引用。这与它对玩家全局处理的其他对象的工作方式没有什么不同,例如,加载器。我知道有一个例外:运行Timers。只要Timer正在运行,即使您没有任何ActionScript引用,它也不会被收集。